Skip to content

Update Gleam Chess Bot for JavaScript support #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# build-your-own-gleam-chess-bot

Content for the "Build your own Gleam Chess Bot" challenge
Content for the "Build your own Gleam Chess Bot (JS)" challenge

### Setup

Expand Down
3 changes: 2 additions & 1 deletion compiled_starters/gleam/.codecrafters/compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@

set -e # Exit on failure

gleam export erlang-shipment
gleam deps download
gleam build --target javascript
4 changes: 3 additions & 1 deletion compiled_starters/gleam/.codecrafters/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
# Learn more: https://codecrafters.io/program-interface

set -e # Exit on failure
exec ./build/erlang-shipment/entrypoint.sh run "$@"

echo "main()" >> build/dev/javascript/chess_bot/chess_bot.mjs
deno run --allow-net build/dev/javascript/chess_bot/chess_bot.mjs
2 changes: 1 addition & 1 deletion compiled_starters/gleam/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*.beam
*.ez
/build
erl_crash.dump
erl_crash.dump
2 changes: 1 addition & 1 deletion compiled_starters/gleam/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/gleam-chess-bot.png)

This is a starting point for Gleam solutions to the
["Build Your Own Gleam Chess Bot" Challenge](https://codecrafters.io/challenges/gleam-chess-bot).
["Build Your Own Gleam Chess Bot (JS)" Challenge](https://codecrafters.io/challenges/gleam-chess-bot).

In this challenge, you'll build a chess bot that's capable of parsing FEN
strings and making valid chess moves.
Expand Down
4 changes: 2 additions & 2 deletions compiled_starters/gleam/codecrafters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ debug: true
# Use this to change the Gleam version used to run your code
# on Codecrafters.
#
# Available versions: gleam-1.9
language_pack: gleam-1.9
# Available versions: gleam-1.10
language_pack: gleam-1.10
18 changes: 12 additions & 6 deletions compiled_starters/gleam/gleam.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
name = "chess_bot"
version = "1.0.0"
target = "erlang"
target = "javascript"

[javascript]
runtime = "deno"

[javascript.deno]
allow_all = true

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
Expand All @@ -14,11 +20,11 @@ target = "erlang"
# https://gleam.run/writing-gleam/gleam-toml/.

[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
wisp = ">= 1.5.3 and < 2.0.0"
mist = ">= 4.0.7 and < 5.0.0"
gleam_stdlib = ">= 0.44.0 and < 2.0.0"
glen = ">= 2.2.2 and < 3.0.0"
gleam_javascript = ">= 1.0.0 and < 2.0.0"
gleam_json = ">= 2.3.0 and < 3.0.0"
gleam_erlang = ">= 0.34.0 and < 1.0.0"
gleam_http = ">= 3.7.2 and < 4.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
gleeunit = ">= 1.0.0 and < 2.0.0"
32 changes: 11 additions & 21 deletions compiled_starters/gleam/manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,24 @@
# You typically do not need to edit this file

packages = [
{ name = "directories", version = "1.1.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "BDA521A4EB9EE3A7894F0DC863797878E91FF5C7826F7084B2E731E208BDB076" },
{ name = "envoy", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "95FD059345AA982E89A0B6E2A3BF1CF43E17A7048DCD85B5B65D3B9E4E39D359" },
{ name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" },
{ name = "conversation", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_javascript", "gleam_stdlib"], otp_app = "conversation", source = "hex", outer_checksum = "103DF47463B8432AB713D6643DC17244B9C82E2B172A343150805129FE584A2F" },
{ name = "filepath", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "67A6D15FB39EEB69DD31F8C145BB5A421790581BD6AA14B33D64D5A55DBD6587" },
{ name = "gleam_crypto", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "8AE56026B3E05EBB1F076778478A762E9EB62B31AEEB4285755452F397029D22" },
{ name = "gleam_erlang", version = "0.34.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "0C38F2A128BAA0CEF17C3000BD2097EB80634E239CE31A86400C4416A5D0FDCC" },
{ name = "gleam_http", version = "4.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "0A62451FC85B98062E0907659D92E6A89F5F3C0FBE4AB8046C99936BF6F91DBC" },
{ name = "gleam_community_ansi", version = "1.4.2", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "479DEDC748D08B310C9FEB9C4CBEC46B95C874F7F4F2844304D6D20CA78A8BB5" },
{ name = "gleam_community_colour", version = "1.4.1", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "386CB9B01B33371538672EEA8A6375A0A0ADEF41F17C86DDCB81C92AD00DA610" },
{ name = "gleam_http", version = "3.7.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8A70D2F70BB7CFEB5DF048A2183FFBA91AF6D4CF5798504841744A16999E33D2" },
{ name = "gleam_javascript", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "EF6C77A506F026C6FB37941889477CD5E4234FCD4337FF0E9384E297CB8F97EB" },
{ name = "gleam_json", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "C55C5C2B318533A8072D221C5E06E5A75711C129E420DD1CE463342106012E5D" },
{ name = "gleam_otp", version = "0.16.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "50DA1539FC8E8FA09924EB36A67A2BBB0AD6B27BCDED5A7EF627057CF69D035E" },
{ name = "gleam_regexp", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "7F5E0C0BBEB3C58E57C9CB05FA9002F970C85AD4A63BA1E55CBCB35C15809179" },
{ name = "gleam_stdlib", version = "0.55.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "32D8F4AE03771516950047813A9E359249BD9FBA5C33463FDB7B953D6F8E896B" },
{ name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" },
{ name = "gleeunit", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "0E6C83834BA65EDCAAF4FE4FB94AC697D9262D83E6F58A750D63C9F6C8A9D9FF" },
{ name = "glisten", version = "7.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging", "telemetry"], otp_app = "glisten", source = "hex", outer_checksum = "1A53CF9FB3231A93FF7F1BD519A43DC968C1722F126CDD278403A78725FC5189" },
{ name = "gramps", version = "3.0.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "59194B3980110B403EE6B75330DB82CDE05FC8138491C2EAEACBC7AAEF30B2E8" },
{ name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
{ name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" },
{ name = "glen", version = "2.2.2", build_tools = ["gleam"], requirements = ["conversation", "filepath", "gleam_community_ansi", "gleam_http", "gleam_javascript", "gleam_stdlib", "marceau"], otp_app = "glen", source = "hex", outer_checksum = "62DF8F8305650237B58B7F29C01016383950479D35FCD8393800CAB94675B0DE" },
{ name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" },
{ name = "mist", version = "4.0.7", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "gleam_yielder", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "F7D15A1E3232E124C7CE31900253633434E59B34ED0E99F273DEE61CDB573CDD" },
{ name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" },
{ name = "simplifile", version = "2.2.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0DFABEF7DC7A9E2FF4BB27B108034E60C81BEBFCB7AB816B9E7E18ED4503ACD8" },
{ name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" },
{ name = "wisp", version = "1.5.3", build_tools = ["gleam"], requirements = ["directories", "exception", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "DCD083E0ED3D30EA8CF2EECCA01A8108F7987D7BD908F527862E3D2725436444" },
]

[requirements]
gleam_erlang = { version = ">= 0.34.0 and < 1.0.0" }
gleam_http = { version = ">= 3.7.2 and < 4.0.0" }
gleam_javascript = { version = ">= 1.0.0 and < 2.0.0" }
gleam_json = { version = ">= 2.3.0 and < 3.0.0" }
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
mist = { version = ">= 4.0.7 and < 5.0.0" }
wisp = { version = ">= 1.5.3 and < 2.0.0" }
glen = { version = ">= 2.2.2 and < 3.0.0" }
100 changes: 41 additions & 59 deletions compiled_starters/gleam/src/chess_bot.gleam
Original file line number Diff line number Diff line change
@@ -1,67 +1,49 @@
import chess_bot/chess

import gleam/dynamic/decode
import gleam/erlang/process
import gleam/io
import gleam/javascript/promise.{type Promise}
import gleam/json
import mist
import wisp.{type Request, type Response}
import wisp/wisp_mist
import glen
import glen/status
import chess_bot/chess
import gleam/io

pub fn main() {
wisp.configure_logger()
wisp.set_logger_level(wisp.CriticalLevel)

let secret_key_base = wisp.random_string(64)

// You can use print statements as follows for debugging, they'll be visible when running tests.
io.println("Logs from your program will appear here!")

// Uncomment this block to pass the first stage
//
// let assert Ok(_) =
// handle_request
// |> wisp_mist.handler(secret_key_base)
// |> mist.new
// |> mist.bind("0.0.0.0")
// |> mist.port(8000)
// |> mist.start_http
//
// process.sleep_forever()
//}
//
// fn handle_request(request: Request) -> Response {
// case wisp.path_segments(request) {
// ["move"] -> handle_move(request)
// _ -> wisp.ok()
// }
// }
// fn move_decoder() {
// use fen <- decode.field("fen", decode.string)
// use turn <- decode.field("turn", chess.player_decoder())
// use failed_moves <- decode.field("failed_moves", decode.list(decode.string))
// decode.success(#(fen, turn, failed_moves))
// }
//
// fn handle_move(request: Request) -> Response {
// use body <- wisp.require_string_body(request)
//
// let decode_result = json.parse(body, move_decoder())
// case decode_result {
// Error(_) -> {
// io.println("Failed to decode JSON")
// wisp.bad_request()
// }
// Ok(move) -> {
// let move_result = chess.move(move.0, move.1, move.2)
// case move_result {
// Ok(move) -> {
// wisp.ok() |> wisp.string_body(move)
// }
// Error(reason) -> {
// wisp.internal_server_error() |> wisp.string_body(reason)
// }
// }
// }
// }
// Uncomment this block to pass the first stage
//
// glen.serve(8000, handle_request)
}

fn handle_request(request: glen.Request) -> Promise(glen.Response) {
case glen.path_segments(request) {
["move"] -> handle_move(request)
_ -> glen.response(status.ok) |> promise.resolve
}
}

fn move_decoder() {
use fen <- decode.field("fen", decode.string)
use turn <- decode.field("turn", chess.player_decoder())
use failed_moves <- decode.field("failed_moves", decode.list(decode.string))
decode.success(#(fen, turn, failed_moves))
}

fn handle_move(request: glen.Request) -> Promise(glen.Response) {
use body <- glen.require_string_body(request)
let decode_result = json.parse(body, move_decoder())
case decode_result {
Error(_) -> glen.response(status.bad_request) |> promise.resolve
Ok(move) -> {
let move_result = chess.move(move.0, move.1, move.2)
case move_result {
Ok(move) ->
glen.response(status.ok) |> glen.text_body(move) |> promise.resolve
Error(reason) ->
glen.response(status.internal_server_error)
|> glen.text_body(reason)
|> promise.resolve
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ pub fn main() {
pub fn hello_world_test() {
1
|> should.equal(1)
}
}
6 changes: 4 additions & 2 deletions compiled_starters/gleam/your_program.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ set -e # Exit early if any commands fail
# - Edit .codecrafters/compile.sh to change how your program compiles remotely
(
cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory
gleam export erlang-shipment
gleam deps download
gleam build --target javascript
)

# Copied from .codecrafters/run.sh
#
# - Edit this to change how your program runs locally
# - Edit .codecrafters/run.sh to change how your program runs remotely
exec ./build/erlang-shipment/entrypoint.sh run "$@"
echo "main()" >> build/dev/javascript/chess_bot/chess_bot.mjs
deno run --allow-net build/dev/javascript/chess_bot/chess_bot.mjs
19 changes: 9 additions & 10 deletions course-definition.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
slug: "gleam-chess-bot"
name: "Build your own Gleam Chess Bot"
slug: "gleam-chess-bot-js"
name: "Build your own Gleam Chess Bot (JS)"
short_name: "Chess Bot"
release_status: "beta"
visibility: "private"
Expand Down Expand Up @@ -57,7 +57,7 @@ marketing:
Didn't even know that was possible!

stages:
- slug: "si0"
- slug: "qc6"
name: "Respond to /move request"
difficulty: easy
description_md: |-
Expand Down Expand Up @@ -96,7 +96,7 @@ stages:
marketing_md: |-
In this stage, you'll create a basic HTTP server that can respond to chess move requests.

- slug: "xt9"
- slug: "zo3"
name: "Respond with an opening"
difficulty: medium
description_md: |-
Expand Down Expand Up @@ -125,7 +125,7 @@ stages:
marketing_md: |-
Make your bot play real chess moves by implementing a simple opening strategy.

- slug: "wd4"
- slug: "xs2"
name: "Bratko-Kopec test"
difficulty: hard
description_md: |-
Expand Down Expand Up @@ -159,7 +159,7 @@ stages:
marketing_md: |-
Test your bot's tactical abilities against the famous Bratko-Kopec test positions.

- slug: "zz5"
- slug: "ix8"
name: "Win at Chess"
difficulty: hard
description_md: |-
Expand Down Expand Up @@ -193,14 +193,14 @@ stages:
- Your bot must make moves within the 5 second time limit
marketing_md: |-
Create a complete chess engine that can play and win full games.
- slug: "gd8"

- slug: "dx9"
name: "Submit your bot"
difficulty: easy
description_md: |-
In this stage, you'll finalize your submission for the tournament.

There is an `example.ENTRY.md` file in the starter code that was provided. You will need to rename the file to `ENTRY.md` and fill in the required fields.
There is an `example.ENTRY.md` file in the starter code that was provided. You will need to rename the file to `ENTRY.md` and fill in the required fields.
You need to mention your name, email and the URL to your repository.

If you don't intend to participate in the tournament, you don't need to fill the details.
Expand All @@ -214,4 +214,3 @@ stages:
- Please do not remove the `example.ENTRY.md` file, before you are ready to submit.
marketing_md: |-
Submit your bot to the tournament.

Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# syntax=docker/dockerfile:1.7-labs
FROM ghcr.io/gleam-lang/gleam:v1.9.1-erlang-alpine
FROM ghcr.io/gleam-lang/gleam:v1.10.0-node-slim

ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="gleam.toml,manifest.toml"

WORKDIR /app
COPY --exclude=.git --exclude=README.md . /app

RUN gleam export erlang-shipment
RUN gleam deps download
RUN gleam build --target javascript

RUN npm install -g [email protected]

# Cache build directory
RUN mkdir -p /app-cached
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@

set -e # Exit on failure

gleam export erlang-shipment
gleam deps download
gleam build --target javascript
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
# Learn more: https://codecrafters.io/program-interface

set -e # Exit on failure
exec ./build/erlang-shipment/entrypoint.sh run "$@"

echo "main()" >> build/dev/javascript/chess_bot/chess_bot.mjs
deno run --allow-net build/dev/javascript/chess_bot/chess_bot.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*.beam
*.ez
/build
erl_crash.dump
erl_crash.dump
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/gleam-chess-bot.png)

This is a starting point for Gleam solutions to the
["Build Your Own Gleam Chess Bot" Challenge](https://codecrafters.io/challenges/gleam-chess-bot).
["Build Your Own Gleam Chess Bot (JS)" Challenge](https://codecrafters.io/challenges/gleam-chess-bot).

In this challenge, you'll build a chess bot that's capable of parsing FEN
strings and making valid chess moves.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ debug: true
# Use this to change the Gleam version used to run your code
# on Codecrafters.
#
# Available versions: gleam-1.9
language_pack: gleam-1.9
# Available versions: gleam-1.10
language_pack: gleam-1.10
Loading
Loading