Skip to content
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

Add a WebSocket example to the demo #136

Open
programarivm opened this issue Feb 18, 2024 · 4 comments
Open

Add a WebSocket example to the demo #136

programarivm opened this issue Feb 18, 2024 · 4 comments

Comments

@programarivm
Copy link

👋 Hi there,

Alternatively to chess.js which is a great JavaScript library, the chess functionality can also be provided by a WebSocket chess server using a different approach. This is the case for PHP Chess Server as shown in the example below.

output_trimmed_enhanced_reduced

// index.js

import {INPUT_EVENT_TYPE, COLOR, Chessboard, BORDER_TYPE} from "cm-chessboard";
import {Accessibility} from "../../../vendor/cm-chessboard/src/extensions/accessibility/Accessibility.js";
import {MARKER_TYPE, Markers} from "../../../vendor/cm-chessboard/src/extensions/markers/Markers.js";
import {FEN} from "../../../vendor/cm-chessboard/src/model/Position.js";
import {PromotionDialog} from "../../../vendor/cm-chessboard/src/extensions/promotion-dialog/PromotionDialog.js";
import Ws from './Ws.js';

const inputHandler = (event) => {
  if (event.type === INPUT_EVENT_TYPE.movingOverSquare) {
    return;
  }

  if (event.type !== INPUT_EVENT_TYPE.moveInputFinished) {
    event.chessboard.removeMarkers(MARKER_TYPE.dot);
    event.chessboard.removeMarkers(MARKER_TYPE.bevel);
  }

  if (event.type === INPUT_EVENT_TYPE.moveInputStarted) {
    ws.send(`/legal ${event.square}`);
    return true;
  } else if (event.type === INPUT_EVENT_TYPE.validateMoveInput) {
    ws.send(`/play_lan ${event.piece.charAt(0)} ${event.squareFrom}${event.squareTo}`);
    return true;
  }
}

const board = new Chessboard(document.getElementById("board"), {
  position: FEN.start,
  assetsUrl: "https://cdn.jsdelivr.net/npm/cm-chessboard@8.5.0/assets/",
  style: {borderType: BORDER_TYPE.none, pieces: {file: "pieces/staunty.svg"}, animationDuration: 300},
  orientation: COLOR.white,
  extensions: [
    {class: Markers, props: {autoMarkers: MARKER_TYPE.square}},
    {class: PromotionDialog},
    {class: Accessibility, props: {visuallyHidden: true}}
  ]
});

board.enableMoveInput(inputHandler);

const ws = new Ws(board);
await ws.connect();
await ws.send('/start classical fen');
// Ws.js

import {MARKER_TYPE} from "../../../vendor/cm-chessboard/src/extensions/markers/Markers.js";

export default class Ws {
  constructor(chessboard) {
    this.chessboard = chessboard;
    this.socket = null;
  }

  connect() {
    console.log('Establishing connection...');

    return new Promise((resolve, reject) => {
      this.socket = new WebSocket('wss://async.chesslablab.org:8443');

      this.socket.onopen = () => {
        console.log('Opened connection!');
        resolve();
      };

      this.socket.onmessage = (res) => {
        const data = JSON.parse(res.data);
        const msg = Object.keys(data)[0];
        switch (true) {
          case 'error' === msg:
            if (data['error']) {
              console.log('Whoops! Something went wrong.');
            }
            break;

          case '/start' === msg:
            if (data['/start'].mode === 'fen') {
              if (data['/start'].fen) {
                console.log('Started FEN!');
              } else {
                console.log('Invalid FEN, please try again with a different one.');
              }
            }
            break;

          case '/legal' === msg:
            if (data['/legal']) {
              Object.keys(data['/legal'].fen).forEach(key => {
                this.chessboard.addMarker(MARKER_TYPE.dot, key);
              });
            }
            break;

          case '/play_lan' === msg:
            if (data['/play_lan'].fen) {
              this.chessboard.setPosition(data['/play_lan'].fen, true);
            }
            break;

          default:
            break;
        }
      };

      this.socket.onclose = (err) => {
        console.log('The connection has been lost, please reload the page.');
        reject(err);
      };

      this.socket.onerror = (err) => {
        console.log('The connection has been lost, please reload the page.');
        reject(err);
      };
    });
  }

  send(message) {
    if (this.socket) {
      this.socket.send(message);
    }
  }
}

I was just wondering if a simple WebSocket example like this one could be added to the cm-chessboard demo.

Thank you, and keep up the great work!

@shaack
Copy link
Owner

shaack commented Jun 24, 2024

Hi @programarivm,this sounds like a good idea for me. But how is it guaranteed, that the websocket server is always available?

@programarivm
Copy link
Author

programarivm commented Jun 25, 2024

Well, you may want to play chess online with other players. This is an alternative architecture based on a WebSocket server as opposed to front-end JavaScript code.

@shaack
Copy link
Owner

shaack commented Jun 25, 2024

How about creating a new project together like a small open source live chess server? To and from this we could connect both sides/projects.

@programarivm
Copy link
Author

programarivm commented Jun 25, 2024

Sounds like a plan!

chesslablab/website is an open-source platform that is using this WebSocket server on AWS. It has an estimated cost of about $12 a month on a t2.micro instance.

screencapture-us-east-1-console-aws-amazon-costmanagement-home-2024-06-25-12_04_12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants