Correct triangular tiling calculations #41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and deploy Pixel2Polygon to GitHub Pages | |
| on: | |
| pull_request: | |
| branches: ["main"] | |
| push: | |
| branches: ["main"] | |
| workflow_dispatch: | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| permissions: | |
| contents: read | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: "pages" | |
| cancel-in-progress: false | |
| jobs: | |
| build: | |
| name: Compile Multilingual sources to WebAssembly | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v5 | |
| - name: Set up Python 3.12 | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: "24" | |
| - name: Install build dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -r requirements-build.txt | |
| - name: Compile Multilingual sources to WebAssembly | |
| run: python -m multilingualprogramming scripts/compile_wasm.ml | |
| - name: Verify build artifacts | |
| run: | | |
| ls -la public | |
| test -f public/index.html | |
| test -f public/style.css | |
| test -f public/app.js | |
| test -f public/hexagonify.wasm | |
| - name: Check JavaScript syntax | |
| run: node --check public/app.js | |
| - name: Validate WASM or fall back to JavaScript-only publish | |
| run: | | |
| node -e " | |
| const fs = require('fs'); | |
| const wasmPath = 'public/hexagonify.wasm'; | |
| const watPath = 'public/hexagonify.wat'; | |
| const fallback = (message, detail) => { | |
| console.warn(message); | |
| if (detail) { | |
| console.warn(detail); | |
| } | |
| if (fs.existsSync(wasmPath)) fs.unlinkSync(wasmPath); | |
| if (fs.existsSync(watPath)) fs.unlinkSync(watPath); | |
| console.log('Publishing JavaScript-only fallback.'); | |
| process.exit(0); | |
| }; | |
| if (!fs.existsSync(wasmPath)) { | |
| fallback('WASM artifact missing after compilation.'); | |
| } | |
| const bytes = fs.readFileSync(wasmPath); | |
| const module = new WebAssembly.Module(bytes); | |
| const importObject = {}; | |
| for (const entry of WebAssembly.Module.imports(module)) { | |
| if (!importObject[entry.module]) { | |
| importObject[entry.module] = {}; | |
| } | |
| if (entry.kind === 'function') { | |
| importObject[entry.module][entry.name] = () => 0; | |
| } else if (entry.kind === 'memory') { | |
| importObject[entry.module][entry.name] = new WebAssembly.Memory({ initial: 16 }); | |
| } else if (entry.kind === 'table') { | |
| importObject[entry.module][entry.name] = new WebAssembly.Table({ initial: 0, element: 'anyfunc' }); | |
| } else if (entry.kind === 'global') { | |
| importObject[entry.module][entry.name] = new WebAssembly.Global({ value: 'i32', mutable: true }, 0); | |
| } | |
| } | |
| if (!importObject.env) { | |
| importObject.env = {}; | |
| } | |
| WebAssembly.instantiate(module, importObject).then((instance) => { | |
| const exports = instance.exports; | |
| const required = [ | |
| 'sommet_hex_x', 'sommet_hex_y', | |
| 'espacement_horiz', 'espacement_vert', | |
| 'hauteur_tri', 'sommet_tri_x', 'sommet_tri_y', | |
| 'generer_tuiles', 'charger_tuile', 'sortie_ptr', | |
| 'methode_hexagone', 'methode_carre', 'methode_triangle', | |
| ]; | |
| const missing = required.filter((name) => typeof exports[name] !== 'function'); | |
| if (missing.length) { | |
| fallback('WASM exports missing.', missing.join(', ')); | |
| } | |
| const checks = [ | |
| ['sommet_hex_x', Number(exports.sommet_hex_x(0, 0, 10, 0)), 0, 0.001], | |
| ['sommet_hex_y', Number(exports.sommet_hex_y(0, 0, 10, 0)), -10, 0.001], | |
| ['espacement_horiz', Number(exports.espacement_horiz(10)), 17.320508, 0.01], | |
| ['espacement_vert', Number(exports.espacement_vert(10)), 15, 0.001], | |
| ['hauteur_tri', Number(exports.hauteur_tri(10)), 8.660254, 0.01], | |
| ['sommet_tri_x', Number(exports.sommet_tri_x(5, 10, 1, 1)), 10, 0.001], | |
| ['sommet_tri_y', Number(exports.sommet_tri_y(5, 10, 2, 0)), 13.660254, 0.01], | |
| ['methode_hexagone', Number(exports.methode_hexagone()), 0, 0.001], | |
| ['methode_carre', Number(exports.methode_carre()), 1, 0.001], | |
| ['methode_triangle', Number(exports.methode_triangle()), 2, 0.001], | |
| ]; | |
| for (const [name, actual, expected, tolerance] of checks) { | |
| if (Math.abs(actual - expected) > tolerance) { | |
| fallback('WASM smoke test failed.', JSON.stringify({ name, expected, actual, tolerance })); | |
| } | |
| } | |
| console.log('WASM smoke test OK'); | |
| }).catch((err) => { | |
| fallback('Could not instantiate WASM.', err && err.stack ? err.stack : String(err)); | |
| }); | |
| " | |
| - name: Configure GitHub Pages | |
| uses: actions/configure-pages@v5 | |
| - name: Upload Pages artifact | |
| uses: actions/upload-pages-artifact@v4 | |
| with: | |
| path: "public" | |
| deploy: | |
| name: Deploy to GitHub Pages | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| needs: build | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - name: Deploy to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v4 |