Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc19d6be53 | ||
|
|
c54023083a | ||
|
|
af6861350d |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+12
-12
@@ -627,9 +627,9 @@
|
|||||||
"file": "andrea-0bd1b0f32e.mp3",
|
"file": "andrea-0bd1b0f32e.mp3",
|
||||||
"sec": 8.7
|
"sec": 8.7
|
||||||
},
|
},
|
||||||
"andrea|Baron! Che ci fai qui?": {
|
"andrea|Barone! Che ci fai qui?": {
|
||||||
"file": "andrea-1b59141c98.mp3",
|
"file": "andrea-83abae1419.mp3",
|
||||||
"sec": 2.59
|
"sec": 2.91
|
||||||
},
|
},
|
||||||
"barondeduke|Aspetto uno che mi deve riportare le mutande.": {
|
"barondeduke|Aspetto uno che mi deve riportare le mutande.": {
|
||||||
"file": "barondeduke-3ea60b7083.mp3",
|
"file": "barondeduke-3ea60b7083.mp3",
|
||||||
@@ -643,9 +643,9 @@
|
|||||||
"file": "barondeduke-5542a06624.mp3",
|
"file": "barondeduke-5542a06624.mp3",
|
||||||
"sec": 1.65
|
"sec": 1.65
|
||||||
},
|
},
|
||||||
"barondeduke|In mano avevo full. E ho detto: «Male male si divide».": {
|
"barondeduke|Avevo due donne e due jack. Entra la terza donna, e penso: «Male male si divide».": {
|
||||||
"file": "barondeduke-944c3e57dc.mp3",
|
"file": "barondeduke-d4ff967179.mp3",
|
||||||
"sec": 5.03
|
"sec": 7.64
|
||||||
},
|
},
|
||||||
"andrea|E invece?": {
|
"andrea|E invece?": {
|
||||||
"file": "andrea-435306c242.mp3",
|
"file": "andrea-435306c242.mp3",
|
||||||
@@ -988,20 +988,20 @@
|
|||||||
"sec": 3.1
|
"sec": 3.1
|
||||||
},
|
},
|
||||||
"tozzino|Aspetto Federer. Oggi si fa una partita.": {
|
"tozzino|Aspetto Federer. Oggi si fa una partita.": {
|
||||||
"file": "tozzino-a069d2c5e2.mp3",
|
"file": "tozzino-c3898e9bdb.mp3",
|
||||||
"sec": 2.85
|
"sec": 3.23
|
||||||
},
|
},
|
||||||
"andrea|Federer? Roger Federer?": {
|
"andrea|Federer? Roger Federer?": {
|
||||||
"file": "andrea-70f150bdec.mp3",
|
"file": "andrea-70f150bdec.mp3",
|
||||||
"sec": 2.67
|
"sec": 2.67
|
||||||
},
|
},
|
||||||
"tozzino|E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.": {
|
"tozzino|E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.": {
|
||||||
"file": "tozzino-5072201408.mp3",
|
"file": "tozzino-d51159c364.mp3",
|
||||||
"sec": 4.3
|
"sec": 4.08
|
||||||
},
|
},
|
||||||
"tozzino|Se non arriva, la vinco a tavolino.": {
|
"tozzino|Se non arriva, la vinco a tavolino.": {
|
||||||
"file": "tozzino-c1736e2d62.mp3",
|
"file": "tozzino-c06cc01612.mp3",
|
||||||
"sec": 1.42
|
"sec": 2.06
|
||||||
},
|
},
|
||||||
"andrea|La Carza. A maggio c'è poca acqua: d'estate si scendeva a fare le dighe coi sassi.": {
|
"andrea|La Carza. A maggio c'è poca acqua: d'estate si scendeva a fare le dighe coi sassi.": {
|
||||||
"file": "andrea-91be1de49b.mp3",
|
"file": "andrea-91be1de49b.mp3",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "leggenda-del-regolo",
|
"name": "leggenda-del-regolo",
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+6
-1
@@ -217,6 +217,7 @@ function filterMap() {
|
|||||||
$('map-none').hidden = shown > 0;
|
$('map-none').hidden = shown > 0;
|
||||||
$('map-none').textContent = `Nessun posto con «${query.trim()}»`;
|
$('map-none').textContent = `Nessun posto con «${query.trim()}»`;
|
||||||
drawRoads();
|
drawRoads();
|
||||||
|
$('map-scroll').scrollTo(0, 0); // i posti rimasti stanno in cima: niente mappa vuota scorsa in fondo
|
||||||
}
|
}
|
||||||
$('map-search').addEventListener('input', filterMap);
|
$('map-search').addEventListener('input', filterMap);
|
||||||
$('map-search').addEventListener('keydown', e => {
|
$('map-search').addEventListener('keydown', e => {
|
||||||
@@ -226,7 +227,11 @@ $('map-search').addEventListener('keydown', e => {
|
|||||||
});
|
});
|
||||||
// Le strade fra le schede, misurate dopo l'impaginazione (e di nuovo se la finestra cambia misura).
|
// Le strade fra le schede, misurate dopo l'impaginazione (e di nuovo se la finestra cambia misura).
|
||||||
function drawRoads() {
|
function drawRoads() {
|
||||||
const board = $('map-board'), svg = $('map-roads'), origin = board.getBoundingClientRect();
|
const board = $('map-board'), svg = $('map-roads');
|
||||||
|
// Prima si toglie la misura vecchia: il disegno delle strade, grande quanto la mappa intera, la terrebbe lunga
|
||||||
|
// anche dopo un filtro.
|
||||||
|
svg.style.width = svg.style.height = '0';
|
||||||
|
const origin = board.getBoundingClientRect();
|
||||||
const center = id => {
|
const center = id => {
|
||||||
const card = board.querySelector(`[data-scene="${id}"]`);
|
const card = board.querySelector(`[data-scene="${id}"]`);
|
||||||
const r = card && !card.hidden && !card.parentElement.hidden && card.querySelector('img').getBoundingClientRect();
|
const r = card && !card.hidden && !card.parentElement.hidden && card.querySelector('img').getBoundingClientRect();
|
||||||
|
|||||||
+2
-2
@@ -1018,11 +1018,11 @@ export const story = {
|
|||||||
actions: {
|
actions: {
|
||||||
look: [{ say: 'Il BaronDeDuke, col cappello da cowboy. Ha l\'aria di uno che aspetta qualcuno, e che spera non lo veda nessuno.' }],
|
look: [{ say: 'Il BaronDeDuke, col cappello da cowboy. Ha l\'aria di uno che aspetta qualcuno, e che spera non lo veda nessuno.' }],
|
||||||
talk: [
|
talk: [
|
||||||
{ say: 'Baron! Che ci fai qui?' },
|
{ say: 'Barone! Che ci fai qui?' },
|
||||||
{ say: 'Aspetto uno che mi deve riportare le mutande.', who: 'barondeduke' },
|
{ say: 'Aspetto uno che mi deve riportare le mutande.', who: 'barondeduke' },
|
||||||
{ say: 'Le... mutande?' },
|
{ say: 'Le... mutande?' },
|
||||||
{ say: 'Le ho perse a poker, ieri sera.', who: 'barondeduke', pose: 'facepalm' },
|
{ say: 'Le ho perse a poker, ieri sera.', who: 'barondeduke', pose: 'facepalm' },
|
||||||
{ say: 'In mano avevo full. E ho detto: «Male male si divide».', who: 'barondeduke', pose: 'cards' },
|
{ say: 'Avevo due donne e due jack. Entra la terza donna, e penso: «Male male si divide».', who: 'barondeduke', pose: 'cards' },
|
||||||
{ say: 'E invece?' },
|
{ say: 'E invece?' },
|
||||||
{ say: 'L\'altro aveva colore.', who: 'barondeduke', pose: 'shrug' },
|
{ say: 'L\'altro aveva colore.', who: 'barondeduke', pose: 'shrug' },
|
||||||
],
|
],
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// La versione del gioco: la cambia scripts/bump.sh, insieme a package.json.
|
// La versione del gioco: la cambia scripts/bump.sh, insieme a package.json.
|
||||||
export const VERSION = '0.1.2';
|
export const VERSION = '0.1.3';
|
||||||
|
|
||||||
// Immagini, musiche e voci con ?v=<versione>: a ogni versione l'indirizzo cambia e il browser le riscarica,
|
// Immagini, musiche e voci con ?v=<versione>: a ogni versione l'indirizzo cambia e il browser le riscarica,
|
||||||
// mentre fra una versione e l'altra le tiene in cache a lungo (nginx.conf).
|
// mentre fra una versione e l'altra le tiene in cache a lungo (nginx.conf).
|
||||||
|
|||||||
@@ -2,14 +2,13 @@
|
|||||||
// ritagli dei nuovi effetti, pause degli animali e nessuna modifica alla partita.
|
// ritagli dei nuovi effetti, pause degli animali e nessuna modifica alla partita.
|
||||||
// npm run browser:effects — immagini in /tmp/regolo-effects (oppure $OUT).
|
// npm run browser:effects — immagini in /tmp/regolo-effects (oppure $OUT).
|
||||||
import { chromium } from 'playwright';
|
import { chromium } from 'playwright';
|
||||||
import { spawn } from 'node:child_process';
|
import { staticServer } from './helpers.mjs';
|
||||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
|
|
||||||
const out = process.env.OUT ?? '/tmp/regolo-effects';
|
const out = process.env.OUT ?? '/tmp/regolo-effects';
|
||||||
mkdirSync(out, { recursive: true });
|
mkdirSync(out, { recursive: true });
|
||||||
const port = 9000 + Math.floor(Math.random() * 900);
|
const server = await staticServer(), port = server.port;
|
||||||
const server = spawn('python3', ['-m', 'http.server', String(port), '--bind', '127.0.0.1'], { stdio: 'ignore' });
|
|
||||||
let browser;
|
let browser;
|
||||||
try {
|
try {
|
||||||
browser = await chromium.launch({ args: ['--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
browser = await chromium.launch({ args: ['--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||||
|
|||||||
+19
-3
@@ -2,14 +2,14 @@
|
|||||||
// fino alla fine, salvataggio e impaginazione su telefono. Schermate in $OUT (predefinito: /tmp/regolo-shots).
|
// fino alla fine, salvataggio e impaginazione su telefono. Schermate in $OUT (predefinito: /tmp/regolo-shots).
|
||||||
// npm run browser
|
// npm run browser
|
||||||
import { chromium } from 'playwright';
|
import { chromium } from 'playwright';
|
||||||
import { spawn } from 'node:child_process';
|
import { staticServer } from './helpers.mjs';
|
||||||
import { mkdirSync, readFileSync } from 'node:fs';
|
import { mkdirSync, readFileSync } from 'node:fs';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import { solution, route } from '../src/story/solution.js';
|
import { solution, route } from '../src/story/solution.js';
|
||||||
|
|
||||||
const OUT = process.env.OUT ?? '/tmp/regolo-shots', PORT = 8000 + Math.floor(Math.random() * 900);
|
const OUT = process.env.OUT ?? '/tmp/regolo-shots';
|
||||||
mkdirSync(OUT, { recursive: true });
|
mkdirSync(OUT, { recursive: true });
|
||||||
const server = spawn('python3', ['-m', 'http.server', String(PORT), '--bind', '127.0.0.1'], { stdio: 'ignore' });
|
const server = await staticServer(), PORT = server.port;
|
||||||
const browser = await chromium.launch({ args: ['--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
const browser = await chromium.launch({ args: ['--use-gl=angle', '--use-angle=swiftshader', '--enable-unsafe-swiftshader'] });
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
|
||||||
@@ -276,6 +276,22 @@ try {
|
|||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
assert.ok(await page.isHidden('#map'));
|
assert.ok(await page.isHidden('#map'));
|
||||||
assert.equal(await page.evaluate(() => game.state.scene), 'piazza');
|
assert.equal(await page.evaluate(() => game.state.scene), 'piazza');
|
||||||
|
// Con tutti i posti visti e la finestra piccola la mappa si scorre: filtrando da in fondo, i posti trovati si vedono
|
||||||
|
// (prima la mappa restava lunga quanto quella intera, scorsa su un fondo vuoto).
|
||||||
|
await page.setViewportSize({ width: 560, height: 340 });
|
||||||
|
await page.evaluate(() => { for (const id of Object.keys(game.story.scenes)) game.state.flags['visto:' + id] = true; });
|
||||||
|
await page.click('#map-button');
|
||||||
|
assert.ok(await page.evaluate(() => { const s = document.getElementById('map-scroll'); s.scrollTop = s.scrollHeight; return s.scrollTop > 0; }), 'la mappa piena si scorre');
|
||||||
|
await page.fill('#map-search', 'campo');
|
||||||
|
const found = await page.evaluate(() => {
|
||||||
|
const s = document.getElementById('map-scroll'), r = s.getBoundingClientRect();
|
||||||
|
const c = [...document.querySelectorAll('#map-board button')].find(b => !b.hidden && !b.parentElement.hidden).getBoundingClientRect();
|
||||||
|
return { inside: c.top >= r.top && c.bottom <= r.bottom, scrollTop: s.scrollTop, h: s.scrollHeight, ch: s.clientHeight, top: c.top - r.top, q: document.getElementById('map-search').value };
|
||||||
|
});
|
||||||
|
assert.ok(found.inside, `filtrando, il primo posto trovato non si vede: ${JSON.stringify(found)}`);
|
||||||
|
await page.screenshot({ path: `${OUT}/07d-mappa-ricerca-piccola.png` });
|
||||||
|
await page.click('#close-map');
|
||||||
|
await page.setViewportSize({ width: 1280, height: 860 });
|
||||||
|
|
||||||
const phone = await open({ width: 390, height: 844 });
|
const phone = await open({ width: 390, height: 844 });
|
||||||
await phone.click('#splash'); // un clic salta il cartello
|
await phone.click('#splash'); // un clic salta il cartello
|
||||||
|
|||||||
@@ -16,3 +16,16 @@ export function settle(game, { maxSteps = 20000 } = {}) {
|
|||||||
export function memoryStorage() {
|
export function memoryStorage() {
|
||||||
return { data: {}, getItem(k) { return this.data[k] ?? null; }, setItem(k, v) { this.data[k] = String(v); }, removeItem(k) { delete this.data[k]; } };
|
return { data: {}, getItem(k) { return this.data[k] ?? null; }, setItem(k, v) { this.data[k] = String(v); }, removeItem(k) { delete this.data[k]; } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Il server statico delle prove nel browser, su una porta libera scelta dal sistema: con una porta a caso poteva
|
||||||
|
// capitare la 8080 del gioco in Docker (make up), e la prova girava sul codice vecchio del container.
|
||||||
|
export async function staticServer() {
|
||||||
|
const { spawn } = await import('node:child_process');
|
||||||
|
const server = spawn('python3', ['-u', '-m', 'http.server', '0', '--bind', '127.0.0.1'], { stdio: ['ignore', 'pipe', 'ignore'] });
|
||||||
|
const port = await new Promise((resolve, reject) => {
|
||||||
|
let out = '';
|
||||||
|
server.stdout.on('data', d => { out += d; const m = out.match(/port (\d+)/); if (m) resolve(Number(m[1])); });
|
||||||
|
server.on('exit', () => reject(new Error('il server di prova non è partito')));
|
||||||
|
});
|
||||||
|
return { port, kill: () => server.kill() };
|
||||||
|
}
|
||||||
|
|||||||
@@ -478,6 +478,6 @@ test('gli amici in giro: l\'Arcu al circolino, il Tozzino al cancello del tennis
|
|||||||
assert.deepEqual(talk('campomigliaio_circolo', 'arcu'), ['andrea: Arcu! Ma che è sempre là, Borgo?', 'arcu: E chi lo sposta???']);
|
assert.deepEqual(talk('campomigliaio_circolo', 'arcu'), ['andrea: Arcu! Ma che è sempre là, Borgo?', 'arcu: E chi lo sposta???']);
|
||||||
assert.ok(talk('carza', 'tozzino').includes('tozzino: E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.'));
|
assert.ok(talk('carza', 'tozzino').includes('tozzino: E chi sennò? Ha chiamato ora: è imbottigliato in Bolognese.'));
|
||||||
const baron = talk('polisportiva', 'barondeduke');
|
const baron = talk('polisportiva', 'barondeduke');
|
||||||
assert.ok(baron.includes('barondeduke: In mano avevo full. E ho detto: «Male male si divide».'));
|
assert.ok(baron.includes('barondeduke: Avevo due donne e due jack. Entra la terza donna, e penso: «Male male si divide».'));
|
||||||
assert.equal(baron.at(-1), 'barondeduke: L\'altro aveva colore.');
|
assert.equal(baron.at(-1), 'barondeduke: L\'altro aveva colore.');
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -8,6 +8,6 @@
|
|||||||
"san_pietro": { "speaker": "Wulf Carlevaro", "filtro": "asetrate=24000*0.92,aresample=24000,atempo=0.95,aecho=0.8:0.6:60:0.2" },
|
"san_pietro": { "speaker": "Wulf Carlevaro", "filtro": "asetrate=24000*0.92,aresample=24000,atempo=0.95,aecho=0.8:0.6:60:0.2" },
|
||||||
"tosca": { "speaker": "Gitta Nikolina" },
|
"tosca": { "speaker": "Gitta Nikolina" },
|
||||||
"arcu": { "speaker": "Luis Moray" },
|
"arcu": { "speaker": "Luis Moray" },
|
||||||
"tozzino": { "speaker": "Dionisio Schuyler" },
|
"tozzino": { "speaker": "Xavier Hayasaka", "filtro": "asetrate=24000*1.12,aresample=24000,atempo=0.92" },
|
||||||
"barondeduke": { "speaker": "Craig Gutsy" }
|
"barondeduke": { "speaker": "Craig Gutsy" }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user