Provide the source code of a microcontroller or tiny computer in JavaScript. Node.js-based computers are supported. Require f3js package and use its API to design the device enclosure.
// instantiate sensors and actuators
var groveSensor = require('jsupm_grove');
var gcl = require("jsupm_my9221");
var button1 = new groveSensor.GroveButton(2);
var button2 = new groveSensor.GroveButton(3);
var LCD = require("jsupm_i2clcd");
var lcd = new LCD.Jhd1313m1(6, 0x3E, 0x62);
var Buzzer = require("jsupm_buzzer");
var buzzer = new Buzzer.Buzzer(4);
// set layout parameters
var f3js = require('f3js')
  , x = 10
  , y = 10
  , useCountdown = true /* Use the countdown feature. */
  , width = useCountdown ? 140 : 60
  , height = 105
  , thickness = 45 /* Thickness [10, 100] */
  , dw = 5 /* Joint width [0, 10]  */
  , dh = 2 /* Joint height (panel thickness) [0, 10] */;
// put base board
var rect = f3js.drawJointRectangle(x, y, width, height, dw, dh, true);
var planes = rect.extrude(thickness);
planes[4].x = width; planes[4].y = 0; f3js.add(planes[4]);
// put sensors and actuators
f3js.drawRectangle(x + 100, y + 55, 10, 6);
f3js.add(button1, { x: x + 105, y: y + 75 });
f3js.drawRectangle(x + 30, y + 55, 10, 6);
f3js.add(button2, { x: 35 + x, y: 75 + y });
f3js.drawRectangle(x + 65, y + 55, 10, 6);
f3js.add(buzzer, { x: 70 + x, y: 75 + y });
f3js.add(lcd, { x: 70 + x, y: 30 + y });
// draw circles...
//for (var i = 0; i < 7; i ++) {
//  f3js.drawCircle(
//        x + width - (i + 1) * 10
//      , y + height - 10
//      , 1); // additional holes
//}
// put side boards
var margin = dh;
planes[0].x = x;
planes[0].y = y + height + margin;
f3js.add(planes[0]);
planes[1].x = x + width;
planes[1].y = y + height + margin - dh;
f3js.add(planes[1]);
planes[2].x = x + height;
planes[2].y = y + height + thickness + margin;
f3js.add(planes[2]);
planes[3].x = x;
planes[3].y = y + height + thickness + margin;
f3js.add(planes[3]);
// put a side hall
planes[3].drawRectangle(
    5, thickness - dh - 15,
    height - 10, 10);
    
function transition(callback) {
    setTimeout(function() {
	    callback();
	}, 200);
}
function transitionByInput(button, down_callback, up_callback) {
    if (button.value() > 0) {
	down_callback();
	var interval = setInterval(function() {
		if (button.value() === 0) {
		    clearInterval(interval);
		    up_callback();
		}
	    }, 100);
    }
}
function waitUntilInput(b1_callback, b2_callback) {
    var interval = setInterval(function() {
	    if (b1_callback != null && button1.value() > 0) {
		clearInterval(interval);
		interval = setInterval(function() {
			if (button1.value() === 0) {
			    clearInterval(interval);
			    b1_callback();
			}
		    });
	    } else if (b2_callback != null && button2.value() > 0) {
		clearInterval(interval);
		interval = setInterval(function() {
			if (button2.value() === 0) {
			    clearInterval(interval);
			    b2_callback();
			}
		    });
	    }
	}, 100);
}
function startIdle() { 
    writeScreen(0, 0, 'Press button    ');
    writeScreen(1, 0, '       to start!');
    waitUntilInput(needTrial, needTrial);
}    
var interval, state = 0;
// direction : 0が右、1が左
function pointingAnimation(direction, count, callback) {
    var array = [
		 ['     (^_^)      ',
		  '     ( ^_^)     ',
		  '     ( ^_^)>    ',
		  '     ( ^_^)=>   '],
		 ['     (^_^)      ',
		  '    (^_^ )      ',
		  '   <(^_^ )      ',
		  '  <=(^_^ )      '],
		 ];
    animateArray(array[direction], 1, count, callback);
}
function gameAnimation(icount, tcount, bcount, callback) {
    var direction = Math.floor(Math.random() * 2);
    setTimeout(function() {
	    pointingAnimation(direction, icount, function(){});
	}, tcount * 3 > icount * 4 ? tcount * 3 - icount * 4 : 0);
    setTimeout(function() {
	    animateArray([
			  'Look            ',
			  'Look this       ',
			  'Look this way!  '
			  ], 0, tcount, function() {});
	}, tcount * 3 < icount * 4 ? icount * 4 - tcount * 3 : 0);
    var state = 0;
    var button = -1;
    var interval = setInterval(function() {
	    if (state >= icount * 4 + (icount < 150 ? 150 : icount) + bcount) {
		clearInterval(interval);
		var result = -1;
		if (direction === button) {
		    result = 1;
		} else if (button !== -1) {
		    result = 0;
		}
		callback(result);
	    }
	    state += 100;
	    if (button === -1) {
		if (button1.value() > 0) {
		    button = 0;
		} else if (button2.value() > 0) {
		    button = 1;
		}
	    }
	}, 100);
}
function needTrial() {
    writeScreen(0, 0, 'Need practice?  ');
    writeScreen(1, 0, ' Yes         No ');
    waitUntilInput(plactice, readyAnimation);
}
function plactice1() {
    resetScreen();
    pointingAnimation(0, 400, function() {
	    var state = 0;
	    var interval = setInterval(function() {
		    var array = [
				 [
				  'Press the other ',
				  '   side of him. '
				  ],
				 [
				  '                ',
				  '     ( ^_^)=>   '
				  ]
				 ];
		    writeScreen(0, 0, array[state][0]);
		    writeScreen(1, 0, array[state][1]);
		    state = state + 1;
		    if (state === 2) {
			state = 0;
		    }
		}, 1500);
	    waitUntilInput(function() {
		    clearInterval(interval);
		    resetScreen();
		    writeScreen(0, 0,         '   Well done!   ');
		    setTimeout(function() {
			    writeScreen(0, 0, 'Let\'s practice  ');
                            writeScreen(1, 0, '   one more time.');
			    setTimeout(plactice2, 1500);
			}, 1500);
		}, null);
	});
}
function plactice2() {
    resetScreen();
    pointingAnimation(1, 400, function() {
	    var state = 0;
	    var interval = setInterval(function() {
		    var array = [
				 [
				  'Press the other ',
				  '   side of him. '
				  ],
				 [
				  '                ',
				  '  <=(^_^ )      '
				  ]
				 ];
		    writeScreen(0, 0, array[state][0]);
		    writeScreen(1, 0, array[state][1]);
		    state = state + 1;
		    if (state === 2) {
			state = 0;
		    }
		}, 1500);
	    waitUntilInput(null, function() {
		    clearInterval(interval);
		    resetScreen();
		    writeScreen(0, 0, '     Great!     ');
		    setTimeout(plactice3, 1500);
		});
	});
}
function plactice3() {
    resetScreen();
    writeScreen(0, 0, 'Let\'s go to      ');
    writeScreen(1, 0, '  the Next Stage!');
    setTimeout(function() {
	    writeScreen(0, 0, 'This time, press');
	    writeScreen(1, 0, ' button earlier ');
	    setTimeout(function() {
		    writeScreen(0, 0, 'than him.       ');
		    writeScreen(1, 0, '     (^_^)      ');
		    setTimeout(function() {
			    resetScreen();
			    writeScreen(0, 0, '   Let\'s try!   ');
			    setTimeout(plactice4, 1500);
			}, 2500);
		}, 3000);
	}, 2000);
}
function plactice4() {
    gameAnimation(400, 500, 1000, function(result) {
	    if (result === -1) {
		writeScreen(0, 0, '    Failed...   ');
		writeScreen(1, 0, '                ');
		setTimeout(function() {
			writeScreen(0, 0, '  One more     ');
			writeScreen(1, 0, '       chance! ');
			setTimeout(plactice4, 1500);
		    }, 1500);
	    } else if (result === 0) {
		writeScreen(0, 0, 'Wrong choice..  ');
		writeScreen(1, 0, '   but good try!');
		setTimeout(function() {
			writeScreen(0, 0, '  One more     ');
			writeScreen(1, 0, '       chance! ');
			setTimeout(plactice4, 1500);
		    }, 1500);
	    } else if (result === 1) {
		writeScreen(0, 0, '   Wonderful!   ');
		writeScreen(1, 0, '                ');
		setTimeout(function() {
			writeScreen(0, 0, 'This one must be');
			writeScreen(1, 0, '   much harder. ');
			setTimeout(plactice5, 2500);
		    }, 1500);
	    } else {
		console.log("???");
	    }
	});
}
function plactice5() {
    gameAnimation(400, 500, 0, function(result) {
	    if (result === -1) {
		writeScreen(0, 0, '    Failed...   ');
		writeScreen(1, 0, '                ');
		setTimeout(function() {
			writeScreen(0, 0, '  One more     ');
			writeScreen(1, 0, '       chance! ');
			setTimeout(plactice5, 1500);
		    }, 1500);
	    } else if (result === 0) {
		writeScreen(0, 0, 'Wrong choice..  ');
		writeScreen(1, 0, '   but good try!');
		setTimeout(function() {
			writeScreen(0, 0, '  One more     ');
			writeScreen(1, 0, '       chance! ');
			setTimeout(plactice5, 1500);
		    }, 1500);
	    } else if (result === 1) {
		writeScreen(0, 0, '  Unbelievable! ');
		writeScreen(1, 0, '                ');
		setTimeout(function() {
			writeScreen(0, 0, 'Practice lesson');
			writeScreen(1, 0, '  is all done. ');
			setTimeout(function() {
				writeScreen(0, 0, 'Now, let\'s      ');
				writeScreen(1, 0, '    start game! ');
				setTimeout(readyAnimation, 2500);
			    }, 2500);
		    }, 1500);
	    } else {
		console.log("???");
	    }
	});
}
	
function plactice() {
    resetScreen();
    animateArray([
		  '                ',
		  ')               ',
		  '^)              ',
		  '_^)             ',
		  '^_^)            ',
		  '(^_^)           ',
		  ' (^_^)          ',
		  '  (^_^)         ',
		  '   (^_^)        ',
		  '    (^_^)       ',
		  '     (^_^)      ',
		  ], 1, 100, plactice1);
}
function readyAnimation() {
    resetScreen();
    animateArray([
		  'Ready?          ',
		  'Ready? 3        ',
		  'Ready? 3..2     ',
		  'Ready? 3..2..1  ',
		  'Start!          ',
		  ], 0, 700, function() {
		     setTimeout(function() {
			     var count = 3;
			     var statei = 4;
			     var u_win = 0;
			     var m_win = 0;
			     var state = [
					  {
					      icount: 100,
					      tcount: 150,
					      face:   '     (@_@)      '
					  },
					  {
					      icount: 100,
					      tcount: 150,
					      face:   '     (=_=)      '
					  },
					  {
					      icount: 100,
					      tcount: 200,
					      face:   '     (*_*)      '
					  },
					  {
					      icount: 150,
					      tcount: 250,
					      face:   '     (>_<)      '
					  },
					  {
					      icount: 200,
					      tcount: 300,
					      face:   '     (^_^)      '
					  },
					  {
					      icount: 300,
					      tcount: 400,
					      face:   '    v(^_^)v     '
					  },
					  {
					      icount: 400,
					      tcount: 500,
					      face:   '    v(^_^)v     '
					  },
					  {
					      icount: 500,
					      tcount: 600,
					      face:   '    V(^_^)V     '
					  },
					  {
					      icount: 500,
					      tcount: 600,
					      face:   '    V(^_^)V     '
					  }
					  ];
			     function gameloop() {
				 resetScreen();
				 gameAnimation(state[statei].icount, state[statei].tcount, 0, function(result) {
					 resetScreen();
					 var rastate = 0;
					 var rainterval = setInterval(function() {
						 if (rastate % 2 === 0) {
						     if (result == 1) {
							 lcd.setColor(0, 0, 255);
						     } else {
							 lcd.setColor(255, 0, 0);
						     }
						 } else {
						     lcd.setColor(255, 255, 255);
						 }
						 if (rastate === 3) {
						     clearInterval(rainterval);
						     resetScreen();
						     if (result == 1) {
							 u_win = u_win + 1;
							 statei = statei - 1;
						     } else {
							 m_win = m_win + 1;
							 statei = statei + 1;
						     }
						     if (count === 0) {
							 var tresult = 2;
							 if (u_win > m_win) {
							     tresult = 0;
							 } else if (u_win < m_win) {
							     tresult = 1;
							 }
							 writeScreen(0, 0, ['You win!!!      ', 'You loose...    ', 'draw game       '][tresult]);
							 writeScreen(1, 0, '     ' + u_win + ' - ' + m_win + '      ');
							 setTimeout(function() {
								 writeScreen(0, 0, '   Continue?    ');
								 writeScreen(1, 0, ' Yes         No ');
								 waitUntilInput(readyAnimation, startIdle);
							     }, 2500);
							 return;
						     }
						     writeScreen(0, 0, '     ' + u_win + ' - ' + m_win + '      ');
						     writeScreen(1, 0, state[statei].face);
						     count = count - 1;
						     setTimeout(gameloop, 1500);
						     return;
						 }
						 rastate = rastate + 1;
					     }, 170);
				     });
			     }
			     gameloop();
			 }, 700);
		 });
}
function animateArray(array, line, count, callback) {
    var state = 0;
    var interval = setInterval(function() {
	    writeScreen(line, 0, array[state]);
	    state = state + 1;
	    if (state === array.length) {
		clearInterval(interval);
		callback();
	    }
	}, count);
}
function writeScreen(x, y, str) {
    lcd.setCursor(x, y);
    lcd.write(str);
}
function resetScreen() {
    lcd.setColor(255, 255, 255);
    lcd.clear();
}
startIdle();