diff --git a/game.js b/game.js index 2354e82..958635d 100644 --- a/game.js +++ b/game.js @@ -1,6 +1,9 @@ const { QLog, undefinedOrNull } = require('quanto-commons'); const player = require('node-wav-player'); -const { Telegraf } = require('telegraf') +const TelegramBot = require('node-telegram-bot-api'); +const fs = require('fs'); +const { exec } = require("child_process"); + if(process.platform !== 'darwin') var gpio = require('rpi-gpio'); const telegramBotToken = '5472909337:AAGH269wNGa9u99ekJqHqXEHfi0knpV7IFU'; @@ -15,10 +18,14 @@ TelLog.enableLogs(['warn']); GlobalLog.headPadding = 30; TelLog.headPadding = 30; -const bot = new Telegraf(telegramBotToken); +// const bot = new Telegraf(telegramBotToken); +const bot = new TelegramBot(telegramBotToken, {polling: true}); // debounce der buttons in ms -const bounceMS = 400; +const bounceMS = 800; + +// Game Reset Start after ms +const startReset = 4000; // ist an wenn im kind mode (erw LED is aus) const childLED = 37; @@ -31,22 +38,27 @@ const failSwitch = 35; // warte auf spielstart wenn auf HIGH const startButton = 32; +const startButton_GPIO = 12; // beende spiel wenn auf HIGH // const finishButton = 31; const finishButton = 22; +const finishButton_GPIO = 25; // faile spiel wenn auf HIGH // const failButton = 29; const failButton = 21; +const failButton_GPIO = 9; // wechsle kind/erwachen Modus + LED const toggleButton = 33; +const toggleButton_GPIO = 13; // wird je nach modus gesetzt und abgespielt wenn start -const backgroundGrown = "northsouth.wav"; +const backgroundGrown = "jaws.wav"; +const jeopardy = "jeopardy.wav"; const backgroundChild = "northsouth.wav"; // wird zufallig zu zufaelligen momenten abgespielt (erw mode) -const erschreckSounds = [ "ziege.wav", "scream.wav", "lough.wav" ]; +const erschreckSounds = [ "ziege.wav", "scream.wav", "laugh.wav", "cavallerie.wav", "gulp.wav" ]; // wird nach fester zeit + random oder spaeter nach der besten zeit abgespielt (erw mode) -const stresserSound = "sharks.wav"; +// const stresserSound = "sharks.wav"; // wird bei fail abgespielt (zonk) const failSound = "zonk.wav"; // hurra wird bei finish abgespielt @@ -72,44 +84,35 @@ var STATE = STATES.FINISH; var MODE = GROWN; var GAME = {}; -var botCTX; +var chatId; -async function sendBotGroupMsg(id,msg) { - if(botCTX) { - botCTX.telegram.sendMessage(id,msg); - } +function sendBotGroupImg(chat_id, photo, caption) { + GlobalLog.info( chat_id, photo); + bot.sendPhoto(chat_id, photo, { + caption: caption + }); } -async function sendBotGroupImg(chat_id, caption, photo) { - if(botCTX) { - botCTX.telegram.sendPhoto( chat_id, photo, caption ); - } -} -async function sendBotMsg(msg) { - if(botCTX) { - botCTX.reply(msg); - } -} -async function sendBotImg(img) { - if(botCTX) { - botCTX.replyWithPhoto({ source: img}); +function sendBotMsg(msg) { + if(chatId) { + bot.sendMessage(chatId, msg); } } -async function setup() { - GlobalLog.start('Running'); - bot.start((ctx) => { - let message = `Bot aktiv und beobachtet. Benutze /stats um die Bestenliste zu sehen`; - ctx.reply(message); - TelLog.note('Bot started'); - botCTX=ctx; - }); - bot.command('stats', async (ctx) => { - await ctx.replyWithPhoto({ source: '/root/hotwire-js/img/bestgrown.png' }); - await ctx.reply(`Bester Erwachsener mit nur ${best.grown} sek`); - await ctx.replyWithPhoto({ source: '/root/hotwire-js/img/bestchild.png' }) - await ctx.reply(`Bestes Kind mit nur ${best.child} sek`); - }); - bot.launch(); +function setup() { + + // bot.start((ctx) => { + // let message = `Bot aktiv und beobachtet. Benutze /stats um die Bestenliste zu sehen`; + // ctx.reply(message); + // TelLog.note('Bot started'); + // botCTX=ctx; + // }); + // bot.command('stats', async (ctx) => { + // await ctx.replyWithPhoto({ source: '/root/hotwire-js/img/bestgrown.png' }); + // await ctx.reply(`Bester Erwachsener mit nur ${best.grown} sek`); + // await ctx.replyWithPhoto({ source: '/root/hotwire-js/img/bestchild.png' }) + // await ctx.reply(`Bestes Kind mit nur ${best.child} sek`); + // }); + // bot.launch(); GlobalLog.note('Setting up GPIOs'); @@ -135,10 +138,18 @@ async function setup() { gpio.output(erwLED, false); }); - gpio.setup(finishButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(toggleButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(startButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(failButton, gpio.DIR_IN, gpio.EDGE_RISING); + gpio.setup(finishButton, gpio.DIR_IN, gpio.EDGE_FALLING, () => { + exec(`raspi-gpio set ${finishButton_GPIO} pu`); + }); + gpio.setup(toggleButton, gpio.DIR_IN, gpio.EDGE_FALLING, () => { + exec(`raspi-gpio set ${toggleButton_GPIO} pu`); + }); + gpio.setup(startButton, gpio.DIR_IN, gpio.EDGE_FALLING, () => { + exec(`raspi-gpio set ${startButton_GPIO} pu`); + }); + gpio.setup(failButton, gpio.DIR_IN, gpio.EDGE_FALLING, () => { + exec(`raspi-gpio set ${failButton_GPIO} pu`); + }); gpio.on('change', (channel, value) => { if(bounce[channel] === true) return; @@ -189,11 +200,14 @@ function start(value) { STATE = STATES.STARTED; // set all params for next game, then start counter and event timer if(MODE === GROWN) { - GAME.events.push({ sound: backgroundGrown, start: 0}); - GAME.events.push({ sound: stresserSound, start: 30+getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 20+getRandomInt(10) }); + if(getRandomInt(7) > 2) { + GAME.events.push({ sound: jeopardy, start: 1}); + } else { + GAME.events.push({ sound: backgroundGrown, start: 1}); + } + GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 15+getRandomInt(10) }); + GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 30+getRandomInt(10) }); + GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 50+getRandomInt(10) }); GAME.mode = GROWN; GAME.fail = failSound; GAME.finish = finishSound; @@ -201,8 +215,7 @@ function start(value) { } if(MODE === CHILD) { GAME.events.push({ sound: backgroundChild, start: 0}); - GAME.events.push({ sound: stresserSound, start: 40+getRandomInt(10)}); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10)}); + GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 30+getRandomInt(10)}); GAME.mode = CHILD; GAME.fail = failSound; GAME.finish = finishSound; @@ -221,26 +234,38 @@ async function finish(value) { if(STATE === STATES.STARTED) { GlobalLog.note('You made it in', GAME.runTime, 'seconds'); GlobalLog.note(GAME); + player.stop(); playSound(GAME.finish); STATE = STATES.FINISH; clearInterval(GAME.countTimer) - GAME.events = []; - await sendBotImg('/tmp/img.png'); - await sendBotMsg(`Gewinner in nur ${GAME.runTime} Sekunden!`); - await sendBotGroupImg(groupid, `Gewinner in nur ${GAME.runTime} Sekunden!`, '/tmp/img.png'); - if(MODE === GROWN) { - if(GAME.runTime < best.grown) { - await sendBotMsg(`Neue Bestzeit bei den Erwachsenen!`); - best.grown = GAME.runTime - // todo copy best img + GlobalLog.note('Getting new image!') + exec(`raspistill -t 1000 -st -o /tmp/last.png`, (err) => { + if(err) { + GloblLog.error('Could not get image', err); } - } else { - if(GAME.runTime < best.child) { - await sendBotMsg(`Neue Bestzeit bei den Kindern!`); - best.child = GAME.runTime - // todo copy best img + GAME.events = []; + var msg; + var img; + if(MODE === GROWN) { + if(GAME.runTime < best.grown) { + best.grown = GAME.runTime; + msg = `Gewinner in nur ${GAME.runTime} Sekunden!\nNeue Bestzeit bei den Erwachsenen!`; + fs.copyFile('/tmp/last.png', '/tmp/bestgrown.png', (err) => {}); + } else { + msg = `Gewinner in nur ${GAME.runTime} Sekunden!`; + } + } else { + if(GAME.runTime < best.child) { + sendBotMsg(`Neue Bestzeit bei den Kindern!`); + best.child = GAME.runTime + msg = `Gewinner in nur ${GAME.runTime} Sekunden!\nNeue Bestzeit bei den Kindern!`; + fs.copyFile('/tmp/last.png', '/tmp/bestchild.png', (err) => {}); + } else { + msg = `Gewinner in nur ${GAME.runTime} Sekunden!`; + } } - } + sendBotGroupImg(groupid, '/tmp/last.png', msg); + }); } else { GlobalLog.warn('FINISH not in state', STATE); } @@ -253,6 +278,7 @@ function fail(value) { STATE = STATES.FAIL; clearInterval(GAME.countTimer) GAME.events = []; + player.stop(); } else { GlobalLog.debug('FAIL not in state', STATE); } @@ -274,15 +300,36 @@ function toggle(value) { } } -function playSound(file){ +function playSound(file, runTime){ if(!file) { GlobalLog.error('Sound not defined.'); return; } GlobalLog.info("Play sound : ", file); if(GAME.playing) { GlobalLog.debug("Stopping old soundfile", GAME.playing); player.stop(); } - GAME.playing = file; + // Do not stop background sound + if(GAME.runTime > 1) { + GAME.playing = file; + } player.play({ path: `wav/${file}`, sync: true }).then(() => { delete GAME.playing }) } setup(); + +TelLog.start('Starting bot...'); +bot.on('message', function (msg) { + const chatId = msg.chat.id; + const resp = msg; + TelLog.info(`${chatId}: ${resp.text}`); + if(resp.text === '/stats') { + TelLog.info(`Dump stats to channel ${groupid}`); + if (fs.existsSync('/tmp/bestchild.png')) { + sendBotGroupImg(groupid, '/tmp/bestchild.png', `Bestes Kind mit ${best.child} Sekunden.`); + } + if (fs.existsSync('/tmp/bestgrown.png')) { + sendBotGroupImg(groupid, '/tmp/bestgrown.png', `Bester Erwachsener mit ${best.grown} Sekunden.`); + } + } +}); + + diff --git a/game.js-2 b/game.js-2 deleted file mode 100644 index 7ea6eaa..0000000 --- a/game.js-2 +++ /dev/null @@ -1,218 +0,0 @@ - -if(process.platform !== 'darwin') var gpio = require('rpi-gpio'); - -const player = require('node-wav-player'); - -// debounce der buttons in ms -const bounceMS = 400; - -// ist an wenn im kind mode (erw LED is aus) -const childLED = 37; -// ist and wenn im erwachsenen Mode (kind LED ist aus) -const erwLED = 38; -// status : ist an wenn in ruhe position, blinkt, wenn gestartet, ist aus bei fail -const statusLED = 40; -// setze auf HIGH wenn fail (klingel relais) -const failSwitch = 35; - -// warte auf spielstart wenn auf HIGH -const startButton = 32; -// beende spiel wenn auf HIGH -const finishButton = 31; -// faile spiel wenn auf HIGH -const failButton = 29; -// wechsle kind/erwachen Modus + LED -const toggleButton = 33; - -// wird je nach modus gesetzt und abgespielt wenn start -const backgroundGrown = "jeopardy.wav"; -const backgroundChild = "northsouth.wav"; -// wird zufallig zu zufaelligen momenten abgespielt (erw mode) -const erschreckSounds = [ "ziege.wav", "scream.wav", "lough.wav" ]; -// wird nach fester zeit + random oder spaeter nach der besten zeit abgespielt (erw mode) -const stresserSound = "sharks.wav"; -// wird bei fail abgespielt (zonk) -const failSound = "zonk.wav"; -// hurra wird bei finish abgespielt -const finishSound = "kidscheering.wav"; - -const GROWN=1; -const CHILD=2; - -const STATES = { - STARTED: 'started', - FINISH: 'finshed', - FAIL: 'failed' -}; - -const bounce = {}; - -var STATE = STATES.FINISH; -var MODE = GROWN; -var GAME = {}; - -function setup() { - console.log('Setting up GPIOs'); - - if(process.platform === 'darwin') { - setTimeout(start, 500); - setTimeout(fail, 3500); - setTimeout(start, 4000); - setTimeout(finish, 9000); - setTimeout(fail, 10000); - setTimeout(finish, 11000); - return; - } - gpio.setup(failSwitch, gpio.OUT, () => { - gpio.output(failSwitch, false); - }); - gpio.setup(statusLED, gpio.OUT, () => { - gpio.output(statusLED, true); - }); - gpio.setup(childLED, gpio.OUT, () => { - gpio.output(childLED, true); - }); - gpio.setup(erwLED, gpio.OUT, () => { - gpio.output(erwLED, false); - }); - - gpio.setup(finishButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(toggleButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(startButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(failButton, gpio.DIR_IN, gpio.EDGE_RISING); - - gpio.on('change', (channel, value) => { - if(bounce[channel] === true) return; - console.log('Change',channel, value); - bounce[channel] = true; - setTimeout(() => { bounce[channel] = false; console.log('Debounced', channel); }, bounceMS); - switch(channel) { - case startButton: - start(value); - break; - case finishButton: - finish(value); - break; - case failButton: - fail(value); - break; - case toggleButton: - toggle(value); - break; - default: - console.log('Alert! Unknown button change',channel); - } - }); - console.log('Done. Game logic started. Waiting for input'); -} - -function gameTimer() { - console.log('game timer called'); - GAME.events.forEach((el) => { - if(el.start === GAME.runTime) { - console.log('Event :', el); - playSound(el.sound); - } - }); - GAME.runTime++; -} - -function getRandomInt(max) { - return Math.floor(Math.random() * max); -} - -function start(value) { - GAME = { - events: [], - runTime: 0 - }; - if(STATE === STATES.FINISH || STATE === STATES.FAIL) { - STATE = STATES.STARTED; - }; - if(STATE === STATES.FINISH || STATE === STATES.FAIL) { - STATE = STATES.STARTED; - }; - if(STATE === STATES.FINISH || STATE === STATES.FAIL) { - STATE = STATES.STARTED; - // set all params for next game, then start counter and event timer - if(MODE === GROWN) { - GAME.events.push({ sound: backgroundGrown, start: 0}); - GAME.events.push({ sound: stresserSound, start: 30+getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 20+getRandomInt(10) }); - GAME.mode = GROWN; - GAME.fail = failSound; - GAME.finish = finishSound; - GAME.runtime = 0; - } - if(MODE === CHILD) { - GAME.events.push({ sound: backgroundChild, start: 0}); - GAME.events.push({ sound: stresserSound, start: 40+getRandomInt(10)}); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10)}); - GAME.mode = CHILD; - GAME.fail = failSound; - GAME.finish = finishSound; - GAME.runtime = 0; - } - console.log('Starting new game', JSON.stringify(GAME, 2, null)); - console.log(GAME); - GAME.countTimer = setInterval(gameTimer, 1000); - } else { - console.log('START not in state', STATE); - } -} - -function finish(value) { - console.log('Finish'); - if(STATE === STATES.STARTED) { - console.log('You made it in', GAME.runTime, 'seconds'); - playSound(GAME.finish); - STATE = STATES.FINISH; - clearInterval(GAME.countTimer) - GAME.events = []; - } else { - console.log('FINISH not in state', STATE); - } -} - -function fail(value) { - console.log('Fail'); - if(STATE === STATES.STARTED) { - console.log('You failed after', GAME.runTime, 'seconds'); - playSound(GAME.fail); - STATE = STATES.FAIL; - clearInterval(GAME.countTimer) - GAME.events = []; - } else { - console.log('FAIL not in state', STATE); - } -} - -function toggle(value) { - if(STATE === STATES.FINISH || STATE === STATES.FAIL) { - console.log('Toggle'); - if(MODE === CHILD) { - MODE = GROWN; - // set all values for GROWN mode - } - if(MODE === GROWN) { - MODE = CHILD; - // set all values for CHILD mode - } - } else { - console.log('Toggle not in state', STATE); - } -} - -function playSound(file){ - console.log("Play sound : ", file); - if(global.GAME.playing) { - console.log("Stopping old soundfile", global.GAME.playing); - player.stop(); - } - global.GAME.playing = file; - player.play({ path: `wav/${file}`, sync: true }).then(() => { delete global.GAME.playing }) -} - -setup(); diff --git a/game.js-global b/game.js-global deleted file mode 100644 index 04f6c44..0000000 --- a/game.js-global +++ /dev/null @@ -1,209 +0,0 @@ - -if(process.platform !== 'darwin') var gpio = require('rpi-gpio'); - -const player = require('node-wav-player'); - -// ist an wenn im kind mode (erw LED is aus) -const childLED = 37; -// ist and wenn im erwachsenen Mode (kind LED ist aus) -const erwLED = 38; -// status : ist an wenn in ruhe position, blinkt, wenn gestartet, ist aus bei fail -const statusLED = 40; -// setze auf HIGH wenn fail (klingel relais) -const failSwitch = 35; - -// warte auf spielstart wenn auf HIGH -const startButton = 32; -// beende spiel wenn auf HIGH -const finishButton = 31; -// faile spiel wenn auf HIGH -const failButton = 29; -// wechsle kind/erwachen Modus + LED -const toggleButton = 33; - -// wird je nach modus gesetzt und abgespielt wenn start -const backgroundGrown = "jeopardy.wav"; -const backgroundChild = "northsouth.wav"; -// wird zufallig zu zufaelligen momenten abgespielt (erw mode) -const erschreckSounds = [ "ziege.wav", "scream.wav", "lough.wav" ]; -// wird nach fester zeit + random oder spaeter nach der besten zeit abgespielt (erw mode) -const stresserSound = "sharks.wav"; -// wird bei fail abgespielt (zonk) -const failSound = "zonk.wav"; -// hurra wird bei finish abgespielt -const finishSound = "kidscheering.wav"; - -const GROWN=1; -const CHILD=2; - -global.STATES = { - STARTED: 'started', - FINISH: 'finshed', - FAIL: 'failed' -}; - -const bounce = {}; - -global.STATE = STATES.FINISH; -global.MODE = GROWN; -global.GAME = {}; - -function setup() { - console.log('Setting up GPIOs'); - - if(process.platform === 'darwin') { - setTimeout(start, 500); - setTimeout(fail, 3500); - setTimeout(start, 4000); - setTimeout(finish, 9000); - setTimeout(fail, 10000); - setTimeout(finish, 11000); - return; - } - gpio.setup(failSwitch, gpio.OUT, () => { - gpio.output(failSwitch, false); - }); - gpio.setup(statusLED, gpio.OUT, () => { - gpio.output(statusLED, true); - }); - gpio.setup(childLED, gpio.OUT, () => { - gpio.output(childLED, true); - }); - gpio.setup(erwLED, gpio.OUT, () => { - gpio.output(erwLED, false); - }); - - gpio.setup(finishButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(toggleButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(startButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(failButton, gpio.DIR_IN, gpio.EDGE_RISING); - - gpio.on('change', (channel, value) => { - if(bounce[value] === true) return; - console.log('Change',channel, value); - bounce[value] = true; - setTimeout(() => { bounce[value] = false; console.log('Debounced', value); }, 1000); - switch(channel) { - case startButton: - start(value); - break; - case finishButton: - finish(value); - break; - case failButton: - fail(value); - break; - case toggleButton: - toggle(value); - break; - default: - console.log('Alert! Unknown button change',channel); - } - }); - console.log('Done. Game logic started. Waiting for input'); -} - -function gameTimer() { - console.log('game timer called'); - global.GAME.events.forEach((el) => { - if(el.start === global.GAME.runTime) { - console.log('Event :', el); - playSound(el.sound); - } - }); - global.GAME.runTime++; -} - -function getRandomInt(max) { - return Math.floor(Math.random() * max); -} - -function start(value) { - global.GAME = { - events: [], - runTime: 0 - }; - if(global.STATE === global.STATES.FINISH || global.STATE === STATES.FAIL) { - global.STATE = global.STATES.STARTED; - // set all params for next game, then start counter and event timer - if(global.MODE === GROWN) { - global.GAME.events.push({ sound: backgroundGrown, start: 0}); - global.GAME.events.push({ sound: stresserSound, start: 30+getRandomInt(10) }); - global.GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: getRandomInt(10) }); - global.GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10) }); - global.GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 20+getRandomInt(10) }); - global.GAME.mode = GROWN; - global.GAME.fail = failSound; - global.GAME.finish = finishSound; - global.GAME.runtime = 0; - } - if(global.MODE === CHILD) { - global.GAME.events.push({ sound: backgroundChild, start: 0}); - global.GAME.events.push({ sound: stresserSound, start: 40+getRandomInt(10)}); - global.GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10)}); - global.GAME.mode = CHILD; - global.GAME.fail = failSound; - global.GAME.finish = finishSound; - global.GAME.runtime = 0; - } - console.log('Starting new game', JSON.stringify(global.GAME, 2, null)); - console.log(global.GAME); - global.GAME.countTimer = setInterval(gameTimer, 1000); - } else { - console.log('START not in state', global.STATE); - } -} - -function finish(value) { - console.log('Finish'); - if(global.STATE === global.STATES.STARTED) { - console.log('You made it in', global.GAME.runTime, 'seconds'); - playSound(global.GAME.finish); - global.STATE = global.STATES.FINISH; - clearInterval(global.GAME.countTimer) - GAME.events = []; - } else { - console.log('FINISH not in state', global.STATE); - } -} - -function fail(value) { - console.log('Fail'); - if(global.STATE === global.STATES.STARTED) { - console.log('You failed after', global.GAME.runTime, 'seconds'); - playSound(global.GAME.fail); - global.STATE = global.STATES.FAIL; - clearInterval(global.GAME.countTimer) - global.GAME.events = []; - } else { - console.log('FAIL not in state', global.STATE); - } -} - -function toggle(value) { - if(global.STATE === global.STATES.FINISH || global.STATE === global.STATES.FAIL) { - console.log('Toggle'); - if(global.MODE === CHILD) { - global.MODE = GROWN; - // set all values for GROWN mode - } - if(global.MODE === GROWN) { - global.MODE = CHILD; - // set all values for CHILD mode - } - } else { - console.log('Toggle not in state', global.STATE); - } -} - -function playSound(file){ - console.log("Play sound : ", file); - if(global.GAME.playing) { - console.log("Stopping old soundfile", global.GAME.playing); - player.stop(); - } - global.GAME.playing = file; - player.play({ path: `wav/${file}`, sync: true }).then(() => { delete global.GAME.playing }) -} - -setup(); diff --git a/game.js~ b/game.js~ deleted file mode 100644 index 4e7fbb9..0000000 --- a/game.js~ +++ /dev/null @@ -1,209 +0,0 @@ - -if(process.platform !== 'darwin') var gpio = require('rpi-gpio'); - -const player = require('node-wav-player'); - -// ist an wenn im kind mode (erw LED is aus) -const childLED = 37; -// ist and wenn im erwachsenen Mode (kind LED ist aus) -const erwLED = 38; -// status : ist an wenn in ruhe position, blinkt, wenn gestartet, ist aus bei fail -const statusLED = 40; -// setze auf HIGH wenn fail (klingel relais) -const failSwitch = 35; - -// warte auf spielstart wenn auf HIGH -const startButton = 32; -// beende spiel wenn auf HIGH -const finishButton = 31; -// faile spiel wenn auf HIGH -const failButton = 29; -// wechsle kind/erwachen Modus + LED -const toggleButton = 33; - -// wird je nach modus gesetzt und abgespielt wenn start -const backgroundGrown = "jeopardy.wav"; -const backgroundChild = "northsouth.wav"; -// wird zufallig zu zufaelligen momenten abgespielt (erw mode) -const erschreckSounds = [ "ziege.wav", "scream.wav", "lough.wav" ]; -// wird nach fester zeit + random oder spaeter nach der besten zeit abgespielt (erw mode) -const stresserSound = "sharks.wav"; -// wird bei fail abgespielt (zonk) -const failSound = "zonk.wav"; -// hurra wird bei finish abgespielt -const finishSound = "kidscheering.wav"; - -const GROWN=1; -const CHILD=2; - -const STATES = { - STARTED: 'started', - FINISH: 'finshed', - FAIL: 'failed' -}; - -const bounce = {}; - -var STATE = STATES.FINISH; -var MODE = GROWN; -var GAME = {}; - -function setup() { - console.log('Setting up GPIOs'); - - if(process.platform === 'darwin') { - setTimeout(start, 500); - setTimeout(fail, 3500); - setTimeout(start, 4000); - setTimeout(finish, 9000); - setTimeout(fail, 10000); - setTimeout(finish, 11000); - return; - } - gpio.setup(failSwitch, gpio.OUT, () => { - gpio.output(failSwitch, false); - }); - gpio.setup(statusLED, gpio.OUT, () => { - gpio.output(statusLED, true); - }); - gpio.setup(childLED, gpio.OUT, () => { - gpio.output(childLED, true); - }); - gpio.setup(erwLED, gpio.OUT, () => { - gpio.output(erwLED, false); - }); - - gpio.setup(finishButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(toggleButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(startButton, gpio.DIR_IN, gpio.EDGE_RISING); - gpio.setup(failButton, gpio.DIR_IN, gpio.EDGE_RISING); - - gpio.on('change', (channel, value) => { - if(bounce[channel] === true) return; - console.log('Change',channel, value); - bounce[channel] = true; - setTimeout(() => { bounce[channel] = false; console.log('Debounced', channel); }, 500); - switch(channel) { - case startButton: - start(value); - break; - case finishButton: - finish(value); - break; - case failButton: - fail(value); - break; - case toggleButton: - toggle(value); - break; - default: - console.log('Alert! Unknown button change',channel); - } - }); - console.log('Done. Game logic started. Waiting for input'); -} - -function gameTimer() { - console.log('game timer called'); - GAME.events.forEach((el) => { - if(el.start === GAME.runTime) { - console.log('Event :', el); - playSound(el.sound); - } - }); - GAME.runTime++; -} - -function getRandomInt(max) { - return Math.floor(Math.random() * max); -} - -function start(value) { - GAME = { - events: [], - runTime: 0 - }; - if(STATE === STATES.FINISH || STATE === STATES.FAIL) { - STATE = STATES.STARTED; - // set all params for next game, then start counter and event timer - if(MODE === GROWN) { - GAME.events.push({ sound: backgroundGrown, start: 0}); - GAME.events.push({ sound: stresserSound, start: 30+getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10) }); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 20+getRandomInt(10) }); - GAME.mode = GROWN; - GAME.fail = failSound; - GAME.finish = finishSound; - GAME.runtime = 0; - } - if(MODE === CHILD) { - GAME.events.push({ sound: backgroundChild, start: 0}); - GAME.events.push({ sound: stresserSound, start: 40+getRandomInt(10)}); - GAME.events.push({ sound: erschreckSounds[getRandomInt(2)], start: 10+getRandomInt(10)}); - GAME.mode = CHILD; - GAME.fail = failSound; - GAME.finish = finishSound; - GAME.runtime = 0; - } - console.log('Starting new game', JSON.stringify(GAME, 2, null)); - console.log(GAME); - GAME.countTimer = setInterval(gameTimer, 1000); - } else { - console.log('START not in state', STATE); - } -} - -function finish(value) { - console.log('Finish'); - if(STATE === STATES.STARTED) { - console.log('You made it in', GAME.runTime, 'seconds'); - playSound(GAME.finish); - STATE = STATES.FINISH; - clearInterval(GAME.countTimer) - GAME.events = []; - } else { - console.log('FINISH not in state', STATE); - } -} - -function fail(value) { - console.log('Fail'); - if(STATE === STATES.STARTED) { - console.log('You failed after', GAME.runTime, 'seconds'); - playSound(GAME.fail); - STATE = STATES.FAIL; - clearInterval(GAME.countTimer) - GAME.events = []; - } else { - console.log('FAIL not in state', STATE); - } -} - -function toggle(value) { - if(STATE === STATES.FINISH || STATE === STATES.FAIL) { - console.log('Toggle'); - if(MODE === CHILD) { - MODE = GROWN; - // set all values for GROWN mode - } - if(MODE === GROWN) { - MODE = CHILD; - // set all values for CHILD mode - } - } else { - console.log('Toggle not in state', STATE); - } -} - -function playSound(file){ - console.log("Play sound : ", file); - if(GAME.playing) { - console.log("Stopping old soundfile", GAME.playing); - player.stop(); - } - GAME.playing = file; - player.play({ path: `wav/${file}`, sync: true }).then(() => { delete GAME.playing }) -} - -setup(); diff --git a/img.png b/img.png deleted file mode 100644 index 0282e07..0000000 Binary files a/img.png and /dev/null differ diff --git a/mp3/jeopardy.mp3 b/mp3/jeopardy.mp3 index c222187..3335895 100644 Binary files a/mp3/jeopardy.mp3 and b/mp3/jeopardy.mp3 differ diff --git a/mp3/northsouth.mp3 b/mp3/northsouth.mp3 index 247b142..8e82a64 100644 Binary files a/mp3/northsouth.mp3 and b/mp3/northsouth.mp3 differ diff --git a/mp3/scream.mp3 b/mp3/scream.mp3 index c222187..0f6911c 100644 Binary files a/mp3/scream.mp3 and b/mp3/scream.mp3 differ diff --git a/mp3/sharks.mp3 b/mp3/sharks.mp3 deleted file mode 100644 index c222187..0000000 Binary files a/mp3/sharks.mp3 and /dev/null differ diff --git a/mp3/ziege.mp3 b/mp3/ziege.mp3 index c222187..6b06640 100644 Binary files a/mp3/ziege.mp3 and b/mp3/ziege.mp3 differ