/**
* Load models from faceapi
* @async
*/asyncfunctionloadModels(){awaitfaceapi.nets.tinyFaceDetector.loadFromUri("https://www.smile-lose.com/models")awaitfaceapi.nets.faceExpressionNet.loadFromUri("https://www.smile-lose.com/models")}/**
* Setup the webcam stream for the user.
* On success, the stream of the webcam is set to the source of the HTML5 tag.
* On error, the error is logged and the process continue.
*/functionsetupWebcam(){navigator.mediaDevices.getUserMedia({video:true,audio:false}).then(stream=>{webcam.srcObject=streamif (isFirstRound)startFirstRound()}).catch(()=>{document.getElementById("smileStatus").textContent="camera not found"isUsingCamera=falseif (isFirstRound)startFirstRound()})}/**
* Determine if the user is smiling or not by getting the most likely current expression
* using the facepi detection object. Build a array to iterate on each possibility and
* pick the most likely.
* @param {Object} expressions object of expressions
* @return {Boolean}
*/functionisSmiling(expressions){// filtering false positiveconstmaxValue=Math.max(...Object.values(expressions).filter(value=>value<=1))constexpressionsKeys=Object.keys(expressions)constmostLikely=expressionsKeys.filter(expression=>expressions[expression]===maxValue)if (mostLikely[0]&&mostLikely[0]=='happy')returntruereturnfalse}/**
* Set an refresh interval where the faceapi will scan the face of the subject
* and return an object of the most likely expressions.
* Use this detection data to pick an expression and spread background gifs on divs.
* @async
*/asyncfunctionrefreshState(){setInterval(async()=>{constdetections=awaitfaceapi.detectAllFaces(webcam,newfaceapi.TinyFaceDetectorOptions()).withFaceExpressions()if (detections&&detections[0]&&detections[0].expressions){isUsingCamera=trueif (isSmiling(detections[0].expressions)){currentSmileStatus=truedocument.getElementById("smileStatus").textContent="YOU SMILE !"}else{document.getElementById("smileStatus").textContent="not smiling"}}},400)}
/**
* Setup the youtube player using the official API
*/functionsetupYoutubePlayer(){player=newYT.Player('player',{height:'100%',width:'100%',videoId:'ewjkzE6X3BM',playerVars:{'controls':0,'rel':0,'showinfo':0,'modestbranding':1,'iv_load_policy':3,'disablekb':1},events:{'onStateChange':onPlayerStateChange}})}/**
* We want to show the intermissions when a video is over.
* Listening to the event onPlayerStateChange of the youtube api.
*/functiononPlayerStateChange(event){// 0 means the video is overif (event.data===0){player.stopVideo()showIntermission()}}/**
* Entrypoint. This should be use once.
*/functionstartFirstRound(){isFirstRound=falsecurrentSmileStatus=falsedocument.getElementById("loading").style.display='none'document.getElementById('intermission').className='fadeOut'player.playVideo()}/**
* Showing the next video to the user.
* This should be only trigger but the click on next video.
*/functionshowNextVideo(event){event.preventDefault()document.getElementById('loading').style.display='block'document.getElementById('result').style.display='none'if (listOfVideoIds.length){constnextVideoId=extractRandomAvailableVideoId()player.loadVideoById({videoId:nextVideoId})player.playVideo()setTimeout(()=>{currentSmileStatus=falsedocument.getElementById('intermission').className='fadeOut'},1000)}else{showCredit()}}