diff --git a/README.md b/README.md index 8d4233b..e25279a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,43 @@ Right now all the web app does is allow you to create a game, and view the prett See [https://krondor-chess.shuttleapp.rs/](https://krondor-chess.shuttleapp.rs) for deployed version -TODOS: +## Requirements +- Rust & Cargo +- [Shuttle](https://docs.shuttle.rs/getting-started/installation) +- Docker -- [ ] Rendering chess boards -- [ ] Making moves against boards +## Local development and usage + +Run code checks: +```bash +make check +``` + +Run tests: +```bash +make test +``` + +Prepare SQLX queries: +```bash +./bin/queries.sh +``` + +Run locally: +```bash +./bin/run.sh +``` + +## Deployment + +You'll need to get an Api key if you want to deploy to [Shuttle.rs](https://console.shuttle.rs/). It's easy and free to get one :) + +In order to deploy to Shuttle.rs run: +```bash +cargo shuttle deploy +``` +Remember to ensure your repository isn't dirty, your code passes checks, and your migrations are properly version controlled! + +### CI/CD + +This repository comes with workflows for deploying to Shuttle.rs from GitHub. These will run on pushing to `main` if you set up the `SHUTTLE_API_KEY` secret for GitHub actions in your repository. diff --git a/bin/postgres.sh b/bin/postgres.sh index 07bf7a7..deb1bce 100755 --- a/bin/postgres.sh +++ b/bin/postgres.sh @@ -8,12 +8,19 @@ POSTGRES_VOLUME_NAME="krondor-chess-postgres-data" POSTGRES_ROOT_USER="postgres" POSTGRES_ROOT_PASSWORD="postgres" +POSTGRES_DATABASE="krondor-chess-db" + +DATABASE_URL="postgres://${POSTGRES_ROOT_USER}:${POSTGRES_ROOT_PASSWORD}@localhost:5432/${POSTGRES_DATABASE}" CONTAINER_RUNTIME="podman" if which docker &>/dev/null; then CONTAINER_RUNTIME="docker" fi +function database-url { + echo ${DATABASE_URL} +} + function run { start-postgres-container } @@ -41,7 +48,7 @@ function create-postgres-container { --name ${POSTGRES_CONTAINER_NAME} \ --env POSTGRES_USER=${POSTGRES_ROOT_USER} \ --env POSTGRES_PASSWORD=${POSTGRES_ROOT_PASSWORD} \ - --env POSTGRES_DB=postgres \ + --env POSTGRES_DB=${POSTGRES_DATABASE} \ --publish 5432:5432 \ --volume ${POSTGRES_VOLUME_NAME}:/var/lib/postgresql/data \ --detach \ diff --git a/bin/queries.sh b/bin/queries.sh index 086369b..9e6aa56 100755 --- a/bin/queries.sh +++ b/bin/queries.sh @@ -2,8 +2,7 @@ set -o errexit -export DATABASE_URL="postgres://postgres:postgres@localhost:5432/postgres" - +export DATABASE_URL=$(bin/postgres.sh database-url) make postgres sqlx database setup diff --git a/bin/run.sh b/bin/run.sh index 5e45e9e..16d0c43 100755 --- a/bin/run.sh +++ b/bin/run.sh @@ -2,8 +2,7 @@ set -o errexit -export DATABASE_URL="postgres://postgres:postgres@localhost:5432/postgres" - +export DATABASE_URL=$(bin/postgres.sh database-url) make postgres cargo shuttle run \ No newline at end of file diff --git a/src/api/models/api_board.rs b/src/api/models/api_board.rs index 76c22c0..172e620 100644 --- a/src/api/models/api_board.rs +++ b/src/api/models/api_board.rs @@ -1,12 +1,24 @@ use std::convert::TryFrom; use pleco::board::Board; +use pleco::core::sq::SQ as Sq; +use pleco::core::Piece; use crate::database::models::PartialGameWithFen; pub struct ApiBoard { - pub id: String, - pub pretty_string: String, + id: String, + html: String, +} + +impl ApiBoard { + pub fn id(&self) -> &str { + &self.id + } + + pub fn html(&self) -> &str { + &self.html + } } impl TryFrom for ApiBoard { @@ -14,11 +26,57 @@ impl TryFrom for ApiBoard { fn try_from(game: PartialGameWithFen) -> Result { let id = game.id().to_string(); - let board = Board::from_fen(game.current_fen()) - .map_err(|e| ApiBoardError::FenBuilder(format!("{:?}", e)))?; - // TODO: Board rendering here - let pretty_string = board.pretty_string(); - Ok(Self { id, pretty_string }) + let html = render_html_board(game.current_fen())?; + Ok(Self { id, html }) + } +} + +fn render_html_board(fen: &str) -> Result { + let board = Board::from_fen(fen).map_err(|e| ApiBoardError::FenBuilder(format!("{:?}", e)))?; + + let mut html_board = String::new(); + html_board.push_str(""); + + for rank in (0..8).rev() { + html_board.push_str(""); + for file in 0..8 { + let square = Sq::from(rank * 8 + file); + let piece = board.piece_at_sq(square); + let class = if square.on_light_square() { + "light-square" + } else { + "dark-square" + }; + + let piece_string = render_html_piece(piece); + + html_board.push_str(&format!( + "", + class, piece_string + )); + } + html_board.push_str(""); + } + + html_board.push_str("
{}
"); + Ok(html_board) +} + +fn render_html_piece(piece: Piece) -> String { + match piece { + Piece::None => " ".to_string(), + Piece::WhitePawn => "♙".to_string(), + Piece::WhiteKnight => "♘".to_string(), + Piece::WhiteBishop => "♗".to_string(), + Piece::WhiteRook => "♖".to_string(), + Piece::WhiteQueen => "♕".to_string(), + Piece::WhiteKing => "♔".to_string(), + Piece::BlackPawn => "♟︎".to_string(), + Piece::BlackKnight => "♞".to_string(), + Piece::BlackBishop => "♝".to_string(), + Piece::BlackRook => "♜".to_string(), + Piece::BlackQueen => "♛".to_string(), + Piece::BlackKing => "♚".to_string(), } } diff --git a/static/not_found.html b/static/not_found.html deleted file mode 100644 index 3320f72..0000000 --- a/static/not_found.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Page Not Found - - -

404 Page Not Found

-

Sorry, the page you are looking for does not exist.

- Go Back Home - - - diff --git a/static/styles.css b/static/styles.css index aeed300..49d18d5 100644 --- a/static/styles.css +++ b/static/styles.css @@ -9,3 +9,30 @@ table, th, td { border: 1px solid black; padding: 0.25rem; } + +.chess-board { + border-collapse: collapse; + margin: auto; /* Center the board horizontally */ +} + +.chess-row { + height: 50px; /* Adjust the height of rows */ +} + +.chess-cell { + width: 50px; /* Adjust the width of cells */ + height: 50px; /* Ensure cells are square */ + text-align: center; /* Center the piece character */ + vertical-align: middle; /* Align the character vertically */ + font-size: 36px; /* Increase the size of the piece character */ + font-weight: bold; /* Optional: Makes the piece character bold */ + border: 1px solid #333; /* Adds a border to each cell */ +} + +.light-square { + background-color: #f0d9b5; /* Light color for light squares */ +} + +.dark-square { + background-color: #b58863; /* Dark color for dark squares */ +} diff --git a/templates/board.html b/templates/board.html index c281f16..1fa2c8b 100644 --- a/templates/board.html +++ b/templates/board.html @@ -1,11 +1,12 @@ - {% extends "base.html" %} {% block content %}

Board

-
- {{ api_board.pretty_string }} +{% let board_html = api_board.html() %} +{% let board_id = api_board.id() %} +
+ {{ board_html|safe }}
{% endblock %} \ No newline at end of file