Note per sviluppatori

Come creare un nuovo livello

I file specifici per ciascun livello si trovano nella cartella server/src/main/resources/static/levels/<id-livello>. I file vengono inseriti nella cartella static del server affinché il server possa servirli, ma all’interno delle cartelle dei livelli troviamo anche file che vengono utilizzati solamente dalla CLI, come il Dockerfile usato per generare le immagini dei container.

game.json

Ciascun livello deve definire un file di configurazione in JSON, formato come nell’esempio seguente:

{
  "name": "n00b",
  "image": "linux-bomb-n00b",
  "description": {
    "en": "n00b: for beginners",
    "it": "n00b: per principianti"
  },
  "time": 600,
  "steps": 4,
  "error_penality": -1,
  "max_errors": 5
}
  • image è il nome dell’immagine Docker da caricare per il livello (senza il tag specifico per la lingua);
  • time è il tempo a dispozione in secondi;
  • steps è il numero totale di passaggi;
  • error_penality è il numero di punti che vengono sottratti in caso di comandi errati (exit status diverso da 0);
  • max_errors è il numero massimo di errori tollerati prima di far esplodere la bomba.

Dockerfile

La cartella server/src/main/resources/static/levels/base contiene il Dockerfile per l’immagine base necessaria per creare i livelli del gioco. L’immagine base richiede un argomento LANG (es: en_US.UTF-8) che serve per definire la lingua da installare e configurare nel container. Le immagini specificano la lingua utilizzando i tag (es: linux-bomb-base:en).

Ciascun livello ha quindi un Dockerfile per ciascuna lingua. Ogni Dockerfile deve ereditare dall’immagine base specifica per la lingua scelta.

Quando si crea un Dockerfile è importante inserire le risorse del livello rispettando le convenzioni utilizzate dal gioco:

  • il materiale che deve essere editato dall’utente va inserito in /opt/linux-bomb/bomb; l’entrypoint dell’immagine base copia il contenuto di questa cartella nel volume /bomb allo startup del container;
  • il container deve partire con l’utente player (già creato nell’immagine base);
  • eventuali aggiunte al .bashrc vanno inserite creando un file /opt/linux-bomb/.bashrc.

checker.py

Ogni livello deve fornire uno script in Python checker.py. Questo script viene richiamato dal checker principale.

Lo script riceve in input 3 argomenti:

  • bomb_folder: path dove è montata la cartella /bomb sulla macchina host;
  • step: numero dello step corrente nel gioco;
  • lang: lingua scelta dall’utente per giocare.

L’output dello script deve essere sempre composto da 2 numeri: lo step calcolato e il punteggio assegnato.

Esempi:

  • se lo step in input è 1 e l’output è 1 0 significa che il comando eseguito dall’utente non ha prodotto alcun cambiamento;
  • se lo step in input è 1 e l’output è 2 100 significa che l’utente è passato allo step successivo a ha guadagnato 100 punti;
  • se l’output è -1 -1000 significa che l’utente ha fatto esplodere la bomba ed ha perso 1000 punti.

bomb.js

Il file bomb.js definisce un WebComponent il cui tag associato deve essere linux-bomb.

Il componente deve esporre i seguenti metodi:

  • setTimer(): riceve un parametro che corrisponde al tempo rimanente già formattato in “mm:ss”; serve per visualizzare il tempo rimanente all’interno della UI;
  • setStep(): riceve un parametro numerico corrispondente allo step da visualizzare;

Il codice seguente costituisce uno scheletro valido per un nuovo componente:

class LinuxBomb extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
      <!-- TODO: inserire HTML e CSS del componente qui -->
    `;
  }

  setTimer(time) {
    // TODO
  }

  setStep(step) {
    // TODO
  }

  /** Notifica al parent che il rendering del componente è concluso */
  connectedCallback() {
    this.dispatchEvent(new CustomEvent('bomb-rendered', { bubbles: true, composed: true }));
  }
}

Nota: l’import di nuovi font non funziona nei WebComponent. La pagina mette a disposizione 2 font che possono essere usati per le scritte custom all’interno dei livelli: E1234 (usato per gli orologi) e Xolonium.