removing outdated tests
This commit is contained in:
		@@ -1,222 +0,0 @@
 | 
			
		||||
let AWasPressed: boolean
 | 
			
		||||
let BWasPressed: boolean
 | 
			
		||||
let ABWasPressed: boolean
 | 
			
		||||
let wasShake: boolean
 | 
			
		||||
let scoreA: number
 | 
			
		||||
let scoreB: number
 | 
			
		||||
 | 
			
		||||
scoreA = 0
 | 
			
		||||
scoreB = 0
 | 
			
		||||
startIOMonitor()
 | 
			
		||||
let gameTime = getGameTime()
 | 
			
		||||
basic.showLeds(`
 | 
			
		||||
    . . # . .
 | 
			
		||||
    . . # . .
 | 
			
		||||
    . . # # #
 | 
			
		||||
    . . . . .
 | 
			
		||||
    . . . . .
 | 
			
		||||
    `)
 | 
			
		||||
while (!BWasPressed) {
 | 
			
		||||
    basic.pause(100)
 | 
			
		||||
}
 | 
			
		||||
BWasPressed = false
 | 
			
		||||
playOneGame(gameTime)
 | 
			
		||||
showFinalScores(scoreA, scoreB)
 | 
			
		||||
 | 
			
		||||
function startIOMonitor() {
 | 
			
		||||
    input.onButtonPressed(Button.A, () => {
 | 
			
		||||
        AWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    input.onButtonPressed(Button.B, () => {
 | 
			
		||||
        BWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    input.onButtonPressed(Button.AB, () => {
 | 
			
		||||
        ABWasPressed = true
 | 
			
		||||
        AWasPressed = false
 | 
			
		||||
        BWasPressed = false
 | 
			
		||||
    })
 | 
			
		||||
    input.onShake(() => {
 | 
			
		||||
        wasShake = true
 | 
			
		||||
    })
 | 
			
		||||
    AWasPressed = false
 | 
			
		||||
    BWasPressed = false
 | 
			
		||||
    ABWasPressed = false
 | 
			
		||||
    wasShake = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * display score for A and B on same screen as a graphic
 | 
			
		||||
 * this shows a tug of war line, in the middle if scores the same,
 | 
			
		||||
 * Can cope with differences +/-10
 | 
			
		||||
 * @param scoreA1 TODO
 | 
			
		||||
 * @param scoreB1 TODO
 | 
			
		||||
 */
 | 
			
		||||
function showScore(scoreA1: number, scoreB1: number) {
 | 
			
		||||
    let img = images.createImage(`
 | 
			
		||||
        # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   . # . . .   . # . . .   . # . . .   . # . . .   . # . . .   . . # . .   . . . # .   . . . # .   . . . # .   . . . # .   . . . # .   . . . . #   . . . . #   . . . . #   . . . . #   . . . . #
 | 
			
		||||
        # . . . .   # . . . .   # . . . .   # . . . .   . # . . .   . # . . .   . # . . .   . # . . .   . # . . .   . . # . .   . . # . .   . . # . .   . . . # .   . . . # .   . . . # .   . . . # .   . . . # .   . . . . #   . . . . #   . . . . #   . . . . #
 | 
			
		||||
        # . . . .   # . . . .   # . . . .   . # . . .   . # . . .   . # . . .   . # . . .   . # . . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . . # .   . . . # .   . . . # .   . . . # .   . . . # .   . . . . #   . . . . #   . . . . #
 | 
			
		||||
        # . . . .   # . . . .   . # . . .   . # . . .   . # . . .   . # . . .   . # . . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . . # .   . . . # .   . . . # .   . . . # .   . . . # .   . . . . #   . . . . #
 | 
			
		||||
        # . . . .   . # . . .   . # . . .   . # . . .   . # . . .   . # . . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . . # .   . . . # .   . . . # .   . . . # .   . . . # .   . . . . #
 | 
			
		||||
        `)
 | 
			
		||||
    let diff = Math.clamp(-10, 10, scoreB1 - scoreA1)
 | 
			
		||||
    diff = diff + 10
 | 
			
		||||
    img.plotFrame(diff)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * show digits 0..10
 | 
			
		||||
 * @param digits TODO
 | 
			
		||||
 */
 | 
			
		||||
function showDigits(digits: number) {
 | 
			
		||||
    digits = Math.clamp(0, 10, digits)
 | 
			
		||||
    let img = images.createImage(`
 | 
			
		||||
        . . # . .   . . # . .   . # # . .   . # # . .   . # . . .   . # # # .   . . # # .   . # # # .   . . # . .   . . # . .   # . . # .
 | 
			
		||||
        . # . # .   . # # . .   . . . # .   . . . # .   . # . . .   . # . . .   . # . . .   . . . # .   . # . # .   . # . # .   # . # . #
 | 
			
		||||
        . # . # .   . . # . .   . . # . .   . . # . .   . # # # .   . . # # .   . # # . .   . . # . .   . . # . .   . . # # .   # . # . #
 | 
			
		||||
        . # . # .   . . # . .   . # . . .   . . . # .   . . # . .   . . . # .   . # . # .   . # . . .   . # . # .   . . . # .   # . # . #
 | 
			
		||||
        . . # . .   . # # # .   . # # # .   . # # . .   . . # . .   . # # . .   . . # . .   . # . . .   . . # . .   . # # . .   # . . # .
 | 
			
		||||
        `)
 | 
			
		||||
    img.plotFrame(digits)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * show time graphic for time remaining
 | 
			
		||||
 * @param gameTime TODO
 | 
			
		||||
 */
 | 
			
		||||
function showTime(gameTime: number) {
 | 
			
		||||
    let minutes = Math.clamp(0, 10, gameTime / 60)
 | 
			
		||||
    let seconds = gameTime % 60
 | 
			
		||||
    // divide seconds into 10 second stripes
 | 
			
		||||
    let stripes = seconds / 10
 | 
			
		||||
    let img = images.createImage(`
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #
 | 
			
		||||
        . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #
 | 
			
		||||
        `)
 | 
			
		||||
    img.plotFrame(stripes)
 | 
			
		||||
    // leave middle row blank
 | 
			
		||||
    // display up to 10 dots in raster on top two rows
 | 
			
		||||
    if (minutes > 0) {
 | 
			
		||||
        for (let i = 0; i < minutes; i++) {
 | 
			
		||||
            let y = i / 5
 | 
			
		||||
            let x = i % 5
 | 
			
		||||
            led.plot(x, y)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getGameTime(): number {
 | 
			
		||||
    let chosenGameTime = 7
 | 
			
		||||
    showDigits(chosenGameTime)
 | 
			
		||||
    while (!BWasPressed) {
 | 
			
		||||
        if (AWasPressed) {
 | 
			
		||||
            if (chosenGameTime < 10) {
 | 
			
		||||
                chosenGameTime = chosenGameTime + 1
 | 
			
		||||
            } else {
 | 
			
		||||
                chosenGameTime = 1
 | 
			
		||||
            }
 | 
			
		||||
            showDigits(chosenGameTime)
 | 
			
		||||
            AWasPressed = false
 | 
			
		||||
        } else {
 | 
			
		||||
            basic.pause(100)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    BWasPressed = false
 | 
			
		||||
    return chosenGameTime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function playOneGame(gameTime: number) {
 | 
			
		||||
    let gameStartTime = input.runningTime()
 | 
			
		||||
    let gameElapsedTime = 0
 | 
			
		||||
    let gameTimeRemaining = gameTime * 60
 | 
			
		||||
    let timeout = 0
 | 
			
		||||
    let lastDisplayedTime = 0
 | 
			
		||||
    showScore(scoreA, scoreB)
 | 
			
		||||
    let state = "TIME"
 | 
			
		||||
    while (gameTimeRemaining >= 0) {
 | 
			
		||||
        // Tick the game time
 | 
			
		||||
        gameElapsedTime = (input.runningTime() - gameStartTime) / 1000
 | 
			
		||||
        gameTimeRemaining = gameTime * 60 - gameElapsedTime
 | 
			
		||||
        // Handle any global events such as point buttons
 | 
			
		||||
        if (AWasPressed) {
 | 
			
		||||
            AWasPressed = false
 | 
			
		||||
            scoreA = scoreA + 1
 | 
			
		||||
            if (state != "LAST10") {
 | 
			
		||||
                showScore(scoreA, scoreB)
 | 
			
		||||
                state = "SCORE"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (BWasPressed) {
 | 
			
		||||
            BWasPressed = false
 | 
			
		||||
            scoreB = scoreB + 1
 | 
			
		||||
            if (state != "LAST10") {
 | 
			
		||||
                showScore(scoreA, scoreB)
 | 
			
		||||
                state = "SCORE"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Handle global transitions
 | 
			
		||||
        if (gameTimeRemaining <= 10 && state != "LAST10") {
 | 
			
		||||
            state = "LAST10"
 | 
			
		||||
        }
 | 
			
		||||
        // Handle game states
 | 
			
		||||
        if (state == "SCORE") {
 | 
			
		||||
            if (wasShake) {
 | 
			
		||||
                wasShake = false
 | 
			
		||||
                showTime(gameTimeRemaining)
 | 
			
		||||
                lastDisplayedTime = gameTimeRemaining
 | 
			
		||||
                timeout = input.runningTime() + 5 * 1000
 | 
			
		||||
                state = "TIME"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "TIME") {
 | 
			
		||||
            if (input.runningTime() > timeout) {
 | 
			
		||||
                showScore(scoreA, scoreB)
 | 
			
		||||
                state = "SCORE"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "LAST10") {
 | 
			
		||||
            if (gameTimeRemaining != lastDisplayedTime) {
 | 
			
		||||
                showDigits(gameTimeRemaining)
 | 
			
		||||
                lastDisplayedTime = gameTimeRemaining
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function showFinalScores(scoreA1: number, scoreB1: number) {
 | 
			
		||||
    basic.showLeds(`
 | 
			
		||||
        # . . . #
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        # . . . #
 | 
			
		||||
        `)
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (AWasPressed) {
 | 
			
		||||
            basic.showString("A", 150)
 | 
			
		||||
            basic.showNumber(scoreA1, 150)
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                # . . . #
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                # . . . #
 | 
			
		||||
                `)
 | 
			
		||||
            AWasPressed = false
 | 
			
		||||
        } else if (BWasPressed) {
 | 
			
		||||
            basic.showString("B", 150)
 | 
			
		||||
            basic.showNumber(scoreB1, 150)
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                # . . . #
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                # . . . #
 | 
			
		||||
                `)
 | 
			
		||||
            BWasPressed = false
 | 
			
		||||
        } else {
 | 
			
		||||
            basic.pause(100)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,248 +0,0 @@
 | 
			
		||||
let speed: number
 | 
			
		||||
let cupCapacity: number
 | 
			
		||||
let maxMisses: number
 | 
			
		||||
let autoEmpty: boolean
 | 
			
		||||
let movement: boolean
 | 
			
		||||
let sensitivity: number
 | 
			
		||||
let cupX: number
 | 
			
		||||
let cupInverted: boolean
 | 
			
		||||
 | 
			
		||||
let highscore = 0
 | 
			
		||||
while (true) {
 | 
			
		||||
    // configure game settings
 | 
			
		||||
    // ##CHALLENGE1: reconfigure game
 | 
			
		||||
    cupCapacity = 5
 | 
			
		||||
    speed = 6
 | 
			
		||||
    maxMisses = 3
 | 
			
		||||
    autoEmpty = false
 | 
			
		||||
    movement = true
 | 
			
		||||
    sensitivity = 400
 | 
			
		||||
    cupX = 2
 | 
			
		||||
    // show the spash screen
 | 
			
		||||
    // ##CHALLENGE 2: CHANGE SPLASH SCREEN
 | 
			
		||||
    basic.showAnimation(`
 | 
			
		||||
        . . . . .   . . . . .
 | 
			
		||||
        . . . . .   . # . # .
 | 
			
		||||
        . . . . .   . . . . .
 | 
			
		||||
        . # . # .   . # . # .
 | 
			
		||||
        . # # # .   . # # # .
 | 
			
		||||
        `, 400)
 | 
			
		||||
    // Decide what to do based on which button is pressed
 | 
			
		||||
    if (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        let finalScore = playGame()
 | 
			
		||||
        // ##CHALLENGE 3 ADD HIGH SCORE
 | 
			
		||||
        if (finalScore > highscore) {
 | 
			
		||||
            basic.showString("HIGH", 150)
 | 
			
		||||
            highscore = finalScore
 | 
			
		||||
        }
 | 
			
		||||
        basic.showNumber(finalScore, 150)
 | 
			
		||||
    } else if (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        testMovement()
 | 
			
		||||
    } else {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function playGame(): number {
 | 
			
		||||
    let cup = images.createImage(`
 | 
			
		||||
        . . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   . # . # .   . . . . .
 | 
			
		||||
        . . . . .   . # # # .   . . . . .
 | 
			
		||||
        `)
 | 
			
		||||
    let score = 0
 | 
			
		||||
    let dropsInCup = 0
 | 
			
		||||
    let misses = 0
 | 
			
		||||
    let dropX = 0
 | 
			
		||||
    let dropY = 0
 | 
			
		||||
    let prevDropY = -1
 | 
			
		||||
    let cupX1 = 2
 | 
			
		||||
    let prevCupX = -1
 | 
			
		||||
    let state = "NEWDROP"
 | 
			
		||||
    startGame()
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (state == "NEWDROP") {
 | 
			
		||||
            // create a new drop at a random position
 | 
			
		||||
            dropX = Math.random(5)
 | 
			
		||||
            dropY = 0
 | 
			
		||||
            state = "RAINING"
 | 
			
		||||
        } else if (state == "RAINING") {
 | 
			
		||||
            // calculate new positions
 | 
			
		||||
            cupX1 = getCupPosition()
 | 
			
		||||
            let thisDropY = dropY / speed
 | 
			
		||||
            // Only redraw the screen if something has changed (prevent flashing)
 | 
			
		||||
            if (cupX1 != prevCupX || thisDropY != prevDropY) {
 | 
			
		||||
                basic.clearScreen()
 | 
			
		||||
                // draw cup
 | 
			
		||||
                cup.showImage(7 - cupX1)
 | 
			
		||||
                if (dropsInCup == cupCapacity) {
 | 
			
		||||
                    // a full cup
 | 
			
		||||
                    led.plot(cupX1, 3)
 | 
			
		||||
                }
 | 
			
		||||
                // draw drop
 | 
			
		||||
                led.plot(dropX, thisDropY)
 | 
			
		||||
                prevCupX = cupX1
 | 
			
		||||
                prevDropY = thisDropY
 | 
			
		||||
            }
 | 
			
		||||
            basic.pause(100)
 | 
			
		||||
            if (thisDropY >= 4) {
 | 
			
		||||
                state = "ATCUP"
 | 
			
		||||
            } else {
 | 
			
		||||
                dropY = dropY + 1
 | 
			
		||||
            }
 | 
			
		||||
            if (cupInverted && dropsInCup >= cupCapacity) {
 | 
			
		||||
                state = "EMPTYING"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "ATCUP") {
 | 
			
		||||
            if (dropX == cupX1) {
 | 
			
		||||
                state = "CATCH"
 | 
			
		||||
            } else {
 | 
			
		||||
                state = "MISS"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "MISS") {
 | 
			
		||||
            // ##CHALLENGE: long beep on miss
 | 
			
		||||
            beep(500)
 | 
			
		||||
            misses = misses + 1
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . # . # .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . # # # .   . # . # .   . . . . .
 | 
			
		||||
                . # . # .   . . . . .   . # # # .   . # . # .
 | 
			
		||||
                . # # # .   . . # . .   . . . . .   . # # # .
 | 
			
		||||
                `, 400)
 | 
			
		||||
            if (misses > maxMisses) {
 | 
			
		||||
                state = "GAMEOVER"
 | 
			
		||||
            } else {
 | 
			
		||||
                state = "NEWDROP"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "CATCH") {
 | 
			
		||||
            // ##CHALLENGE: short beep on catch
 | 
			
		||||
            beep(200)
 | 
			
		||||
            dropsInCup = dropsInCup + 1
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . # # # .   # . # . #   . # . # .
 | 
			
		||||
                . # # # .   # # # # #   . # # # .
 | 
			
		||||
                `, 400)
 | 
			
		||||
            if (dropsInCup == cupCapacity) {
 | 
			
		||||
                state = "FULL"
 | 
			
		||||
                score = score + 1
 | 
			
		||||
            } else if (dropsInCup > cupCapacity) {
 | 
			
		||||
                state = "OVERFLOW"
 | 
			
		||||
            } else {
 | 
			
		||||
                score = score + 1
 | 
			
		||||
                state = "NEWDROP"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "FULL") {
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . # # # .   . . . . .
 | 
			
		||||
                . # # # .   . # # # .   . # # # .
 | 
			
		||||
                . # # # .   . # # # .   . # # # .
 | 
			
		||||
                `, 400)
 | 
			
		||||
            if (autoEmpty) {
 | 
			
		||||
                state = "EMPTYING"
 | 
			
		||||
            } else {
 | 
			
		||||
                state = "NEWDROP"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "EMPTYING") {
 | 
			
		||||
            if (cupInverted) {
 | 
			
		||||
                basic.showAnimation(`
 | 
			
		||||
                    . . . . .   . . . . .   . . . . .   . . # . .   . . . . .
 | 
			
		||||
                    . . . . .   . . . . .   . . # . .   . . . . .   . . . . .
 | 
			
		||||
                    . . . . .   . . # . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                    . # # # .   . # . # .   . # . # .   . # . # .   . # . # .
 | 
			
		||||
                    . # # # .   . # # # .   . # # # .   . # # # .   . # # # .
 | 
			
		||||
                    `, 400)
 | 
			
		||||
            } else {
 | 
			
		||||
                basic.showAnimation(`
 | 
			
		||||
                    . . . . .   . . . . .   . # # # .   . # # # .   . # # # .   . # # # .   . # # # .   . . . . .   . . . . .
 | 
			
		||||
                    . . . . .   . # # . .   . # # # .   . # . # .   . # . # .   . # . # .   . # . # .   . # # . .   . . . . .
 | 
			
		||||
                    . . . . .   . # # . .   . . . . .   . . # . .   . . . . .   . . . . .   . . . . .   . # . . .   . . . . .
 | 
			
		||||
                    . # # # .   . # # . .   . . . . .   . . . . .   . . # . .   . . . . .   . . . . .   . # # . .   . # . # .
 | 
			
		||||
                    . # # # .   . . . . .   . . . . .   . . . . .   . . . . .   . . # . .   . . . . .   . . . . .   . # # # .
 | 
			
		||||
                    `, 400)
 | 
			
		||||
            }
 | 
			
		||||
            dropsInCup = 0
 | 
			
		||||
            // ##CHALLENGE: Speed up on every level change
 | 
			
		||||
            if (speed > 1) {
 | 
			
		||||
                speed = speed - 1
 | 
			
		||||
            }
 | 
			
		||||
            state = "NEWDROP"
 | 
			
		||||
        } else if (state == "OVERFLOW") {
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . # # # .   . # . # .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . # # # .   . # # # .   # # # # #   # # # # #   . # # # .   . # # # .
 | 
			
		||||
                . # # # .   . # # # .   . # # # .   . # # # .   # # # # #   . # # # .
 | 
			
		||||
                `, 400)
 | 
			
		||||
            state = "GAMEOVER"
 | 
			
		||||
        } else if (state == "GAMEOVER") {
 | 
			
		||||
            // ##CHALLENGE: Make a sound on game over
 | 
			
		||||
            beep(700)
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . # # # .   # # # # #   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . # # # .   # # # # #   . # . # .   . . . . .   . . . . .   . # . # .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . # # # .   # # # # #   . # . # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . # . # .   . . . . .   . # # # .   # # # # #   . # . # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . # # # .   # # # # #   . # . # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                `, 400)
 | 
			
		||||
            break
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return score
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testMovement() {
 | 
			
		||||
    while (!input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        // ##CHALLENGE 5: Add accelerometer test mode
 | 
			
		||||
        let x = getCupPosition()
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        led.plot(x, 2)
 | 
			
		||||
        basic.pause(200)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getCupPosition(): number {
 | 
			
		||||
    if (movement) {
 | 
			
		||||
        let acc = input.acceleration(Dimension.X) / sensitivity
 | 
			
		||||
        cupX = Math.clamp(0, 4, acc + 2)
 | 
			
		||||
        return cupX
 | 
			
		||||
    }
 | 
			
		||||
    if (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        if (cupX > 0) {
 | 
			
		||||
            cupX = cupX - 1
 | 
			
		||||
        }
 | 
			
		||||
    } else if (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        if (cupX < 4) {
 | 
			
		||||
            cupX = cupX + 1
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return cupX
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function startGame() {
 | 
			
		||||
    basic.clearScreen()
 | 
			
		||||
    // If button still held from start-game, wait until it is released
 | 
			
		||||
    while (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        // wait for button to be released
 | 
			
		||||
    }
 | 
			
		||||
    // handlers that work out if cup is turned upside down or not
 | 
			
		||||
    input.onLogoDown(() => {
 | 
			
		||||
        cupInverted = true
 | 
			
		||||
    })
 | 
			
		||||
    input.onLogoUp(() => {
 | 
			
		||||
        cupInverted = false
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function beep(p: number) {
 | 
			
		||||
    pins.digitalWritePin(DigitalPin.P0, 1)
 | 
			
		||||
    basic.pause(p)
 | 
			
		||||
    pins.digitalWritePin(DigitalPin.P0, 0)
 | 
			
		||||
}
 | 
			
		||||
@@ -1,716 +0,0 @@
 | 
			
		||||
let AWasPressed: boolean
 | 
			
		||||
let BWasPressed: boolean
 | 
			
		||||
let ABWasPressed: boolean
 | 
			
		||||
let wasShake: boolean
 | 
			
		||||
 | 
			
		||||
startIOMonitor()
 | 
			
		||||
let gameNo = 0
 | 
			
		||||
while (true) {
 | 
			
		||||
    // select a new game
 | 
			
		||||
    if (AWasPressed) {
 | 
			
		||||
        gameNo = (gameNo + 1) % 4
 | 
			
		||||
        AWasPressed = false
 | 
			
		||||
    }
 | 
			
		||||
    // show selected game
 | 
			
		||||
    if (gameNo == 0) {
 | 
			
		||||
        basic.showLeds(`
 | 
			
		||||
            # # # # #
 | 
			
		||||
            # . . . #
 | 
			
		||||
            . # . # .
 | 
			
		||||
            . . . . .
 | 
			
		||||
            . # # # .
 | 
			
		||||
            `)
 | 
			
		||||
    } else if (gameNo == 1) {
 | 
			
		||||
        basic.showLeds(`
 | 
			
		||||
            # # # . .
 | 
			
		||||
            # . . . .
 | 
			
		||||
            # # # # #
 | 
			
		||||
            # # . . .
 | 
			
		||||
            # # # . .
 | 
			
		||||
            `)
 | 
			
		||||
    } else if (gameNo == 2) {
 | 
			
		||||
        basic.showLeds(`
 | 
			
		||||
            . . . . .
 | 
			
		||||
            # . . . .
 | 
			
		||||
            # # # # #
 | 
			
		||||
            # . . . .
 | 
			
		||||
            . . . . .
 | 
			
		||||
            `)
 | 
			
		||||
    } else if (gameNo == 3) {
 | 
			
		||||
        basic.showLeds(`
 | 
			
		||||
            # . # # #
 | 
			
		||||
            # # # # #
 | 
			
		||||
            . . . # #
 | 
			
		||||
            # # # # #
 | 
			
		||||
            # # # # #
 | 
			
		||||
            `)
 | 
			
		||||
    }
 | 
			
		||||
    // start selected game
 | 
			
		||||
    if (BWasPressed) {
 | 
			
		||||
        // Play the selected game
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        waitBReleased()
 | 
			
		||||
        resetButtons()
 | 
			
		||||
        let finalScore = 0
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        if (gameNo == 0) {
 | 
			
		||||
            finalScore = playCybermen()
 | 
			
		||||
        } else if (gameNo == 1) {
 | 
			
		||||
            finalScore = playDalek()
 | 
			
		||||
        } else if (gameNo == 2) {
 | 
			
		||||
            finalScore = playSonicScrewdriver()
 | 
			
		||||
        } else if (gameNo == 3) {
 | 
			
		||||
            finalScore = playJudoonLanguage()
 | 
			
		||||
        }
 | 
			
		||||
        flashDigit(finalScore, 3)
 | 
			
		||||
        resetButtons()
 | 
			
		||||
        waitBPressed()
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        waitBReleased()
 | 
			
		||||
        resetButtons()
 | 
			
		||||
    } else {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Game parameters
 | 
			
		||||
 * Percentage chance that cyberman will move left/right to line up with you
 | 
			
		||||
 */
 | 
			
		||||
function playCybermen(): number {
 | 
			
		||||
    let maxGameTime = 60
 | 
			
		||||
    let cybermanMoveXProbability = 20
 | 
			
		||||
    // How long (in 100ms ticks) cyberman must line up before moving forward
 | 
			
		||||
    let cybermanMoveYCount = 10
 | 
			
		||||
    // Game variables
 | 
			
		||||
    let startTime = input.runningTime()
 | 
			
		||||
    let gameTime = 0
 | 
			
		||||
    let playerX = 2
 | 
			
		||||
    let cybermanX = 1
 | 
			
		||||
    let cybermanY = 0
 | 
			
		||||
    let cybermanLineupCount = 0
 | 
			
		||||
    let redraw = true
 | 
			
		||||
    while (gameTime < maxGameTime) {
 | 
			
		||||
        if (redraw) {
 | 
			
		||||
            basic.clearScreen()
 | 
			
		||||
            led.plot(playerX, 4)
 | 
			
		||||
            led.plot(cybermanX, cybermanY)
 | 
			
		||||
            redraw = false
 | 
			
		||||
        }
 | 
			
		||||
        // Handle Player Movement
 | 
			
		||||
        if (AWasPressed) {
 | 
			
		||||
            if (playerX > 0) {
 | 
			
		||||
                playerX = playerX - 1
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
            AWasPressed = false
 | 
			
		||||
        } else if (BWasPressed) {
 | 
			
		||||
            if (playerX < 4) {
 | 
			
		||||
                playerX = playerX + 1
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
            BWasPressed = false
 | 
			
		||||
        }
 | 
			
		||||
        // Handle Cyberman line-of-sight checking
 | 
			
		||||
        if (cybermanX == playerX) {
 | 
			
		||||
            cybermanLineupCount = cybermanLineupCount + 1
 | 
			
		||||
            if (cybermanLineupCount >= cybermanMoveYCount) {
 | 
			
		||||
                if (cybermanY == 4) {
 | 
			
		||||
                    // Cyberman caught you, game over
 | 
			
		||||
                    break
 | 
			
		||||
                } else {
 | 
			
		||||
                    cybermanY = cybermanY + 1
 | 
			
		||||
                    redraw = true
 | 
			
		||||
                    cybermanLineupCount = 0
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            cybermanLineupCount = 0
 | 
			
		||||
            // Move Cyberman closer to player, slowly
 | 
			
		||||
            if (Math.random(100) < cybermanMoveXProbability) {
 | 
			
		||||
                if (cybermanX > playerX) {
 | 
			
		||||
                    cybermanX = cybermanX - 1
 | 
			
		||||
                } else if (cybermanX < playerX) {
 | 
			
		||||
                    cybermanX = cybermanX + 1
 | 
			
		||||
                }
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
        gameTime = (input.runningTime() - startTime) / 1000
 | 
			
		||||
    }
 | 
			
		||||
    return convertSurvivalTimeToScore(gameTime)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Game parameters, all probabilities as a percentage
 | 
			
		||||
 */
 | 
			
		||||
function playDalek(): number {
 | 
			
		||||
    let maxGameTime = 60
 | 
			
		||||
    let userMoveSensitivity = 40
 | 
			
		||||
    let dalekMoveSensitivity = 20
 | 
			
		||||
    let dalekShootChance = 10
 | 
			
		||||
    let dalekHitChance = 10
 | 
			
		||||
    // Game variables
 | 
			
		||||
    let gameTime = 0
 | 
			
		||||
    let startTime = input.runningTime()
 | 
			
		||||
    let dalekY = 2
 | 
			
		||||
    let userY = 1
 | 
			
		||||
    let redraw = true
 | 
			
		||||
    while (gameTime < maxGameTime) {
 | 
			
		||||
        // Redraw screen if necessary
 | 
			
		||||
        if (redraw) {
 | 
			
		||||
            basic.clearScreen()
 | 
			
		||||
            led.plot(0, dalekY)
 | 
			
		||||
            led.plot(4, userY)
 | 
			
		||||
            redraw = false
 | 
			
		||||
        }
 | 
			
		||||
        // Work out if the user has moved, and move them
 | 
			
		||||
        let tilt = getTilt()
 | 
			
		||||
        if (tilt > 2) {
 | 
			
		||||
            // Moving up, slowly
 | 
			
		||||
            if (userY < 4) {
 | 
			
		||||
                if (Math.random(100) < userMoveSensitivity) {
 | 
			
		||||
                    userY = userY + 1
 | 
			
		||||
                    redraw = true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (tilt < 2) {
 | 
			
		||||
            // Moving down (slowly)
 | 
			
		||||
            if (userY > 0) {
 | 
			
		||||
                if (Math.random(100) < userMoveSensitivity) {
 | 
			
		||||
                    userY = userY - 1
 | 
			
		||||
                    redraw = true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Move the Dalek to line up with user
 | 
			
		||||
        if (dalekY < userY) {
 | 
			
		||||
            if (Math.random(100) < dalekMoveSensitivity) {
 | 
			
		||||
                dalekY = dalekY + 1
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
        } else if (dalekY > userY) {
 | 
			
		||||
            if (Math.random(100) < dalekMoveSensitivity) {
 | 
			
		||||
                dalekY = dalekY - 1
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // Dalek lines up
 | 
			
		||||
            if (Math.random(100) < dalekShootChance) {
 | 
			
		||||
                // Shoot a raygun at the user
 | 
			
		||||
                for (let i = 0; i < 3; i++) {
 | 
			
		||||
                    led.plot(i + 1, dalekY)
 | 
			
		||||
                    basic.pause(100)
 | 
			
		||||
                }
 | 
			
		||||
                if (Math.random(100) < dalekHitChance) {
 | 
			
		||||
                    // User has been hit, game over
 | 
			
		||||
                    break
 | 
			
		||||
                }
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        gameTime = (input.runningTime() - startTime) / 1000
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
    return convertSurvivalTimeToScore(gameTime)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Set this in steps of 60
 | 
			
		||||
 */
 | 
			
		||||
function playSonicScrewdriver(): number {
 | 
			
		||||
    let maxGameTime = 120
 | 
			
		||||
    let gameTime = 0
 | 
			
		||||
    // @=0, A=1 etc
 | 
			
		||||
    // bit0=N, bit1=E, bit2=S, bit3=W
 | 
			
		||||
    // bit=0 means it is a wall (can not be opened)
 | 
			
		||||
    // bit=1 means it is a door (can be opened)
 | 
			
		||||
    let mazestr = "BLFL@GOIFIGLCJIA"
 | 
			
		||||
    let maze = ([] as number[])
 | 
			
		||||
    // Locks use same number encoding (bits 0,1,2,3)
 | 
			
		||||
    // bit=0 means door is locked (cannot be walked through)
 | 
			
		||||
    // bit=1 means door is open (can be walked through)
 | 
			
		||||
    let doorOpen = ([] as number[])
 | 
			
		||||
    for (let i = 0; i < 16; i++) {
 | 
			
		||||
        doorOpen.push(0)
 | 
			
		||||
        maze.push(mazestr.charCodeAt(i) - 64)
 | 
			
		||||
    }
 | 
			
		||||
    let redraw = true
 | 
			
		||||
    let cellno = 0
 | 
			
		||||
    let direction = "N"
 | 
			
		||||
    let startTime = input.runningTime()
 | 
			
		||||
    while (gameTime < maxGameTime) {
 | 
			
		||||
        // Draw the screen
 | 
			
		||||
        if (redraw) {
 | 
			
		||||
            basic.clearScreen()
 | 
			
		||||
            // Always draw the maze with N at the top
 | 
			
		||||
            drawMazeCell(doorOpen[cellno])
 | 
			
		||||
            // draw user standing next to selected wall
 | 
			
		||||
            if (direction == "N") {
 | 
			
		||||
                led.plot(2, 1)
 | 
			
		||||
            } else if (direction == "E") {
 | 
			
		||||
                led.plot(3, 2)
 | 
			
		||||
            } else if (direction == "S") {
 | 
			
		||||
                led.plot(2, 3)
 | 
			
		||||
            } else if (direction == "W") {
 | 
			
		||||
                led.plot(1, 2)
 | 
			
		||||
            }
 | 
			
		||||
            redraw = false
 | 
			
		||||
        }
 | 
			
		||||
        // Sense any button presses
 | 
			
		||||
        if (AWasPressed) {
 | 
			
		||||
            if (direction == "N") {
 | 
			
		||||
                direction = "E"
 | 
			
		||||
            } else if (direction == "E") {
 | 
			
		||||
                direction = "S"
 | 
			
		||||
            } else if (direction == "S") {
 | 
			
		||||
                direction = "W"
 | 
			
		||||
            } else if (direction == "W") {
 | 
			
		||||
                direction = "N"
 | 
			
		||||
            }
 | 
			
		||||
            redraw = true
 | 
			
		||||
            AWasPressed = false
 | 
			
		||||
        } else if (BWasPressed) {
 | 
			
		||||
            // Try to walk through an open door
 | 
			
		||||
            if (isDoorOpen(doorOpen[cellno], direction)) {
 | 
			
		||||
                cellno = mazeForward(cellno, 4, 4, direction)
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
            BWasPressed = false
 | 
			
		||||
        } else if (wasShake) {
 | 
			
		||||
            // energise sonic screwdriver
 | 
			
		||||
            if (isDoorOpen(maze[cellno], direction)) {
 | 
			
		||||
                // It is a door, but is the door open or closed?
 | 
			
		||||
                if (!(isDoorOpen(doorOpen[cellno], direction))) {
 | 
			
		||||
                    // Open the door in front of us
 | 
			
		||||
                    doorOpen[cellno] = openDoor(doorOpen[cellno], direction)
 | 
			
		||||
                    // Also open the return door for when we walk through this door
 | 
			
		||||
                    let forwardCellno = mazeForward(cellno, 4, 4, direction)
 | 
			
		||||
                    doorOpen[forwardCellno] = openDoor(doorOpen[forwardCellno], opposite(direction))
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                // Not a door
 | 
			
		||||
                basic.showLeds(`
 | 
			
		||||
                    . . . . .
 | 
			
		||||
                    . # . # .
 | 
			
		||||
                    . . # . .
 | 
			
		||||
                    . # . # .
 | 
			
		||||
                    . . . . .
 | 
			
		||||
                    `)
 | 
			
		||||
                basic.pause(500)
 | 
			
		||||
            }
 | 
			
		||||
            redraw = true
 | 
			
		||||
            wasShake = false
 | 
			
		||||
        }
 | 
			
		||||
        if (cellno == 15) {
 | 
			
		||||
            // Have reached the exit cell
 | 
			
		||||
            break
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
        gameTime = (input.runningTime() - startTime) / 1000
 | 
			
		||||
    }
 | 
			
		||||
    return convertPenaltyTimeToScore(gameTime / maxGameTime / 60)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function playJudoonLanguage(): number {
 | 
			
		||||
    let maxGameTime = 60
 | 
			
		||||
    let gameTime = 0
 | 
			
		||||
    let startTime = input.runningTime()
 | 
			
		||||
    let font = images.createImage(`
 | 
			
		||||
        # . # # #   # . # . #   . . . . #   # # . . .   # # # # #   # . # . #   # # # . .   . . . # #   # . . . #   # # # # #
 | 
			
		||||
        # # # # #   # # # # #   . . . # #   . # # # #   . # . . .   # # # # #   # # # # #   # # # # .   # # # # #   . . # . .
 | 
			
		||||
        . . . . #   # # # . .   . . # # #   . . . . #   . # . . .   . . . . #   . . . # #   . . # # #   . . # . .   # # # # #
 | 
			
		||||
        # # # # #   # # # # #   . . # . .   # # # # #   # # # # #   # # # # #   # # # # .   # # # # #   # # # # #   # # # . .
 | 
			
		||||
        # # # # #   # # # # #   # # # # #   # . . . .   # . . . #   # . . . .   . . . # #   # # # . .   # # # # #   # # # # #
 | 
			
		||||
        `)
 | 
			
		||||
    let answers = images.createImage(`
 | 
			
		||||
        # # # # #   # # # . .   . # # # .   . . # . .   # . # . #
 | 
			
		||||
        # . . . #   # . . . .   # # # # #   . . . . .   . . . . .
 | 
			
		||||
        . # . # .   # # # # .   # . # . #   . # . # .   # . # . #
 | 
			
		||||
        . . . . .   # # # . .   # . # . #   . . . . .   . . . . .
 | 
			
		||||
        . # # # .   # # # . .   # . # . #   # # # # #   # . . . #
 | 
			
		||||
        `)
 | 
			
		||||
    let pages = "029 041 167 208 283"
 | 
			
		||||
    let actualAnswer = Math.random(5)
 | 
			
		||||
    let pos = 0
 | 
			
		||||
    let redraw = true
 | 
			
		||||
    while (gameTime < maxGameTime) {
 | 
			
		||||
        // Draw the current frame from pos (0,1,2 codeword, 3,4,5,6,7 answers)
 | 
			
		||||
        if (redraw) {
 | 
			
		||||
            if (pos <= 2) {
 | 
			
		||||
                // Draw codeword symbol for this choice and this position
 | 
			
		||||
                let digit = parseInt(pages[actualAnswer * 4 + pos])
 | 
			
		||||
                font.plotFrame(digit)
 | 
			
		||||
            } else {
 | 
			
		||||
                // Draw answer
 | 
			
		||||
                let item = pos - 3
 | 
			
		||||
                answers.plotFrame(item)
 | 
			
		||||
            }
 | 
			
		||||
            redraw = false
 | 
			
		||||
        }
 | 
			
		||||
        // Process button presses
 | 
			
		||||
        if (AWasPressed) {
 | 
			
		||||
            // Move left, unless at far left already
 | 
			
		||||
            AWasPressed = false
 | 
			
		||||
            if (pos > 0) {
 | 
			
		||||
                pos = pos - 1
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
        } else if (BWasPressed) {
 | 
			
		||||
            // Move right, unless already at far right
 | 
			
		||||
            BWasPressed = false
 | 
			
		||||
            if (pos < 7) {
 | 
			
		||||
                pos = pos + 1
 | 
			
		||||
                redraw = true
 | 
			
		||||
            }
 | 
			
		||||
        } else if (wasShake) {
 | 
			
		||||
            // User trying to select an answer, are we at an answer position?
 | 
			
		||||
            wasShake = false
 | 
			
		||||
            if (pos >= 3) {
 | 
			
		||||
                // Is it the right answer?
 | 
			
		||||
                let userChoice = pos - 3
 | 
			
		||||
                if (userChoice == actualAnswer) {
 | 
			
		||||
                    // CORRECT
 | 
			
		||||
                    basic.showAnimation(`
 | 
			
		||||
                        . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                        . . . . .   . . . . .   . . . . .   . . . . .   . . . . #
 | 
			
		||||
                        . . . . .   . . . . .   . . . . .   . . . # .   . . . # .
 | 
			
		||||
                        # . . . .   # . . . .   # . # . .   # . # . .   # . # . .
 | 
			
		||||
                        . . . . .   . # . . .   . # . . .   . # . . .   . # . . .
 | 
			
		||||
                        `, 400)
 | 
			
		||||
                    basic.pause(1000)
 | 
			
		||||
                    break
 | 
			
		||||
                } else {
 | 
			
		||||
                    // WRONG
 | 
			
		||||
                    basic.showAnimation(`
 | 
			
		||||
                        . . . . .   . . . . .   . . . . .   . . . . .   . . . . #   # . . . #   # . . . #   # . . . #   # . . . #
 | 
			
		||||
                        . . . . .   . . . . .   . . . . .   . . . # .   . . . # .   . . . # .   . # . # .   . # . # .   . # . # .
 | 
			
		||||
                        . . . . .   . . . . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .
 | 
			
		||||
                        . . . . .   . # . . .   . # . . .   . # . . .   . # . . .   . # . . .   . # . . .   . # . # .   . # . # .
 | 
			
		||||
                        # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . #
 | 
			
		||||
                        `, 400)
 | 
			
		||||
                    basic.pause(1000)
 | 
			
		||||
                    redraw = true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        gameTime = (input.runningTime() - startTime) / 1000
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
    return convertPenaltyTimeToScore(gameTime)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getDirection(): string {
 | 
			
		||||
    let bearing = input.compassHeading()
 | 
			
		||||
    if (bearing < 45 || bearing > 315) {
 | 
			
		||||
        return "N"
 | 
			
		||||
    } else if (bearing < 135) {
 | 
			
		||||
        return "E"
 | 
			
		||||
    } else if (bearing < 225) {
 | 
			
		||||
        return "S"
 | 
			
		||||
    } else {
 | 
			
		||||
        return "W"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function calibrateCompass() {
 | 
			
		||||
    if (input.compassHeading() == -4) {
 | 
			
		||||
        input.calibrate()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitBReleased() {
 | 
			
		||||
    while (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitBPressed() {
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Show the score 0..9
 | 
			
		||||
 * @param digit TODO
 | 
			
		||||
 * @param times TODO
 | 
			
		||||
 */
 | 
			
		||||
function flashDigit(digit: number, times: number) {
 | 
			
		||||
    digit = Math.clamp(0, 9, digit)
 | 
			
		||||
    for (let i = 0; i < times; i++) {
 | 
			
		||||
        basic.showNumber(digit, 0)
 | 
			
		||||
        basic.pause(500)
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        basic.pause(500)
 | 
			
		||||
    }
 | 
			
		||||
    basic.showNumber(digit, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * score is calculated as the amount of time you lasted
 | 
			
		||||
 * @param gameTime TODO
 | 
			
		||||
 */
 | 
			
		||||
function convertSurvivalTimeToScore(gameTime: number): number {
 | 
			
		||||
    if (gameTime <= 4) {
 | 
			
		||||
        return 0
 | 
			
		||||
    } else if (gameTime <= 9) {
 | 
			
		||||
        return 1
 | 
			
		||||
    } else if (gameTime <= 14) {
 | 
			
		||||
        return 2
 | 
			
		||||
    } else if (gameTime <= 19) {
 | 
			
		||||
        return 3
 | 
			
		||||
    } else if (gameTime <= 24) {
 | 
			
		||||
        return 4
 | 
			
		||||
    } else if (gameTime <= 29) {
 | 
			
		||||
        return 5
 | 
			
		||||
    } else if (gameTime <= 39) {
 | 
			
		||||
        return 6
 | 
			
		||||
    } else if (gameTime <= 49) {
 | 
			
		||||
        return 7
 | 
			
		||||
    } else if (gameTime <= 59) {
 | 
			
		||||
        return 8
 | 
			
		||||
    } else {
 | 
			
		||||
        return 9
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function convertPenaltyTimeToScore(penaltyTime: number): number {
 | 
			
		||||
    if (penaltyTime <= 4) {
 | 
			
		||||
        return 9
 | 
			
		||||
    } else if (penaltyTime <= 9) {
 | 
			
		||||
        return 8
 | 
			
		||||
    } else if (penaltyTime <= 14) {
 | 
			
		||||
        return 7
 | 
			
		||||
    } else if (penaltyTime <= 19) {
 | 
			
		||||
        return 6
 | 
			
		||||
    } else if (penaltyTime <= 24) {
 | 
			
		||||
        return 5
 | 
			
		||||
    } else if (penaltyTime <= 29) {
 | 
			
		||||
        return 4
 | 
			
		||||
    } else if (penaltyTime <= 39) {
 | 
			
		||||
        return 3
 | 
			
		||||
    } else if (penaltyTime <= 49) {
 | 
			
		||||
        return 2
 | 
			
		||||
    } else if (penaltyTime <= 59) {
 | 
			
		||||
        return 1
 | 
			
		||||
    } else {
 | 
			
		||||
        return 0
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function startIOMonitor() {
 | 
			
		||||
    input.onButtonPressed(Button.A, () => {
 | 
			
		||||
        AWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    input.onButtonPressed(Button.B, () => {
 | 
			
		||||
        BWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    input.onButtonPressed(Button.AB, () => {
 | 
			
		||||
        ABWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    input.onShake(() => {
 | 
			
		||||
        wasShake = true
 | 
			
		||||
    })
 | 
			
		||||
    AWasPressed = false
 | 
			
		||||
    BWasPressed = false
 | 
			
		||||
    ABWasPressed = false
 | 
			
		||||
    wasShake = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * maze is always drawn with north at top
 | 
			
		||||
 * @param cell TODO
 | 
			
		||||
 */
 | 
			
		||||
function drawMazeCell(cell: number) {
 | 
			
		||||
    let n = !(isNorth(cell))
 | 
			
		||||
    let e = !(isEast(cell))
 | 
			
		||||
    let s = !(isSouth(cell))
 | 
			
		||||
    let w = !(isWest(cell))
 | 
			
		||||
    // Draw any visible walls
 | 
			
		||||
    if (n) {
 | 
			
		||||
        for (let i = 0; i < 5; i++) {
 | 
			
		||||
            led.plot(i, 0)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (e) {
 | 
			
		||||
        for (let l = 0; l < 5; l++) {
 | 
			
		||||
            led.plot(4, l)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (s) {
 | 
			
		||||
        for (let k = 0; k < 5; k++) {
 | 
			
		||||
            led.plot(k, 4)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (w) {
 | 
			
		||||
        for (let j = 0; j < 5; j++) {
 | 
			
		||||
            led.plot(0, j)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * work out the cell number in front of this cell
 | 
			
		||||
 * given the direction N E S W (N points to button B)
 | 
			
		||||
 * returns the forward cell number, -1 if outside of maze
 | 
			
		||||
 * Turn cellno into an x and y based on width and height
 | 
			
		||||
 * @param cellno TODO
 | 
			
		||||
 * @param width TODO
 | 
			
		||||
 * @param height TODO
 | 
			
		||||
 * @param direction TODO
 | 
			
		||||
 */
 | 
			
		||||
function mazeForward(cellno: number, width: number, height: number, direction: string): number {
 | 
			
		||||
    let y = cellno / width
 | 
			
		||||
    let x = cellno % width
 | 
			
		||||
    // Work out change in x/y and therefore change in cellno
 | 
			
		||||
    // But bounds-check against width and height
 | 
			
		||||
    // as user cannot walk outside of the maze
 | 
			
		||||
    if (direction == "N") {
 | 
			
		||||
        // sub 1 from y
 | 
			
		||||
        if (y > 0) {
 | 
			
		||||
            return cellno - width
 | 
			
		||||
        }
 | 
			
		||||
    } else if (direction == "E") {
 | 
			
		||||
        // Add 1 to x
 | 
			
		||||
        if (x < width - 1) {
 | 
			
		||||
            return cellno + 1
 | 
			
		||||
        }
 | 
			
		||||
    } else if (direction == "S") {
 | 
			
		||||
        // add 1 to y
 | 
			
		||||
        if (y < height - 1) {
 | 
			
		||||
            return cellno + width
 | 
			
		||||
        }
 | 
			
		||||
    } else if (direction == "W") {
 | 
			
		||||
        // sub 1 from x
 | 
			
		||||
        if (x > 0) {
 | 
			
		||||
            return cellno - 1
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Not allowed to move in this direction, it will go outside of maze
 | 
			
		||||
    return - 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A door is open if the lock bit is 1
 | 
			
		||||
 * A door is present if the maze bit is 1
 | 
			
		||||
 * @param cell TODO
 | 
			
		||||
 * @param direction TODO
 | 
			
		||||
 */
 | 
			
		||||
function isDoorOpen(cell: number, direction: string): boolean {
 | 
			
		||||
    if (direction == "N") {
 | 
			
		||||
        return isNorth(cell)
 | 
			
		||||
    } else if (direction == "E") {
 | 
			
		||||
        return isEast(cell)
 | 
			
		||||
    }
 | 
			
		||||
    if (direction == "S") {
 | 
			
		||||
        return isSouth(cell)
 | 
			
		||||
    } else if (direction == "W") {
 | 
			
		||||
        return isWest(cell)
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getTilt(): number {
 | 
			
		||||
    let tilt: number
 | 
			
		||||
    tilt = input.acceleration(Dimension.Y)
 | 
			
		||||
    tilt = Math.clamp(-1024, 1023, tilt)
 | 
			
		||||
    tilt = (tilt + 1024) / 512
 | 
			
		||||
    return tilt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitAReleased() {
 | 
			
		||||
    while (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitNoButtons() {
 | 
			
		||||
    while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B) || input.buttonIsPressed(Button.AB)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function resetButtons() {
 | 
			
		||||
    AWasPressed = false
 | 
			
		||||
    BWasPressed = false
 | 
			
		||||
    ABWasPressed = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The appropriate bit (0,1,2,3) is set, which unlocks the door
 | 
			
		||||
 * @param cell TODO
 | 
			
		||||
 * @param direction TODO
 | 
			
		||||
 */
 | 
			
		||||
function openDoor(cell: number, direction: string): number {
 | 
			
		||||
    if (direction == "N") {
 | 
			
		||||
        return cell | 1
 | 
			
		||||
    } else if (direction == "E") {
 | 
			
		||||
        return cell | 2
 | 
			
		||||
    } else if (direction == "S") {
 | 
			
		||||
        return cell | 4
 | 
			
		||||
    } else if (direction == "W") {
 | 
			
		||||
        return cell | 8
 | 
			
		||||
    }
 | 
			
		||||
    return cell
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * is the north bit set in the cell?
 | 
			
		||||
 * @param cell TODO
 | 
			
		||||
 */
 | 
			
		||||
function isNorth(cell: number): boolean {
 | 
			
		||||
    if ((cell & 1) != 0) {
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * is the east bit set in the cell?
 | 
			
		||||
 * @param cell TODO
 | 
			
		||||
 */
 | 
			
		||||
function isEast(cell: number): boolean {
 | 
			
		||||
    if ((cell & 2) != 0) {
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * is the south bit set in the cell?
 | 
			
		||||
 * @param cell TODO
 | 
			
		||||
 */
 | 
			
		||||
function isSouth(cell: number): boolean {
 | 
			
		||||
    if ((cell & 4) != 0) {
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * is the west bit set in the cell?
 | 
			
		||||
 * @param cell TODO
 | 
			
		||||
 */
 | 
			
		||||
function isWest(cell: number): boolean {
 | 
			
		||||
    if ((cell & 8) != 0) {
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function opposite(direction: string): string {
 | 
			
		||||
    if (direction == "N") {
 | 
			
		||||
        return "S"
 | 
			
		||||
    } else if (direction == "E") {
 | 
			
		||||
        return "W"
 | 
			
		||||
    } else if (direction == "S") {
 | 
			
		||||
        return "N"
 | 
			
		||||
    } else if (direction == "W") {
 | 
			
		||||
        return "E"
 | 
			
		||||
    }
 | 
			
		||||
    return direction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isSount() { }
 | 
			
		||||
@@ -1,165 +0,0 @@
 | 
			
		||||
let sensorType: string
 | 
			
		||||
 | 
			
		||||
// ANALOG or TILT
 | 
			
		||||
sensorType = "TILT"
 | 
			
		||||
while (true) {
 | 
			
		||||
    // splash screen (flood monitor)
 | 
			
		||||
    basic.showLeds(`
 | 
			
		||||
        # # # . .
 | 
			
		||||
        # . . . .
 | 
			
		||||
        # # . # .
 | 
			
		||||
        # . . # .
 | 
			
		||||
        # . . # #
 | 
			
		||||
        `)
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
            // test that the sensor works
 | 
			
		||||
            testMode()
 | 
			
		||||
            break
 | 
			
		||||
        } else if (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
            // run the real flood monitor
 | 
			
		||||
            floodMonitor()
 | 
			
		||||
            break
 | 
			
		||||
        } else {
 | 
			
		||||
            basic.pause(100)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * test mode - test that the monitor and buzzer work
 | 
			
		||||
 * no filtering in this mode, direct screen update
 | 
			
		||||
 */
 | 
			
		||||
function testMode() {
 | 
			
		||||
    basic.showLeds(`
 | 
			
		||||
        # # # # #
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        `)
 | 
			
		||||
    waitNoButtons()
 | 
			
		||||
    let img = images.createImage(`
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   # # # # #
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   # # # # #   . . . . .
 | 
			
		||||
        . . . . .   . . . . .   # # # # #   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   # # # # #   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        # # # # #   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        `)
 | 
			
		||||
    while (!input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        // Show live reading on display
 | 
			
		||||
        let value = readSensor()
 | 
			
		||||
        img.showImage(value * 5)
 | 
			
		||||
        // Turn beeper on only if maximum value seen
 | 
			
		||||
        if (value >= 4) {
 | 
			
		||||
            pins.digitalWritePin(DigitalPin.P1, 1)
 | 
			
		||||
        } else {
 | 
			
		||||
            pins.digitalWritePin(DigitalPin.P1, 0)
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(50)
 | 
			
		||||
    }
 | 
			
		||||
    waitNoButtons()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function floodMonitor() {
 | 
			
		||||
    basic.showLeds(`
 | 
			
		||||
        # . . . #
 | 
			
		||||
        # # . # #
 | 
			
		||||
        # . # . #
 | 
			
		||||
        # . . . #
 | 
			
		||||
        # . . . #
 | 
			
		||||
        `)
 | 
			
		||||
    waitNoButtons()
 | 
			
		||||
    let line = images.createImage(`
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   # # # # #
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   # # # # #   . . . . .
 | 
			
		||||
        . . . . .   . . . . .   # # # # #   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   # # # # #   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        # # # # #   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        `)
 | 
			
		||||
    let state = "SAFE"
 | 
			
		||||
    let averagedValue = 0
 | 
			
		||||
    while (!input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        let value = readSensor()
 | 
			
		||||
        // Apply some 'lag' filtering to the value, so that 'bobbing' doesn't set off alarm
 | 
			
		||||
        // i.e. to go from 0 to 4 takes 4 times round the loop
 | 
			
		||||
        if (value > averagedValue) {
 | 
			
		||||
            // On the way up, changes in reading are slowed down
 | 
			
		||||
            averagedValue = averagedValue + 1
 | 
			
		||||
        } else if (value < averagedValue) {
 | 
			
		||||
            // On the way down, changes in reading happen immediately
 | 
			
		||||
            averagedValue = value
 | 
			
		||||
        }
 | 
			
		||||
        // Work out what to do based on the averaged value (non bobbing value)
 | 
			
		||||
        if (state == "SAFE") {
 | 
			
		||||
            if (averagedValue >= 4) {
 | 
			
		||||
                pins.digitalWritePin(DigitalPin.P1, 1)
 | 
			
		||||
                state = "ALARMING"
 | 
			
		||||
            } else {
 | 
			
		||||
                // Display raw value as a line
 | 
			
		||||
                line.showImage(value * 5)
 | 
			
		||||
                // fill in based on averaged value (long term reading)
 | 
			
		||||
                for (let i = 0; i < averagedValue; i++) {
 | 
			
		||||
                    led.plot(2, 4 - i)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "ALARMING") {
 | 
			
		||||
            if (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
                pins.digitalWritePin(DigitalPin.P1, 0)
 | 
			
		||||
                state = "SAFE"
 | 
			
		||||
            } else {
 | 
			
		||||
                basic.showAnimation(`
 | 
			
		||||
                    # # # # #   . . . . .
 | 
			
		||||
                    # # # # #   . . . . .
 | 
			
		||||
                    # # # # #   . . . . .
 | 
			
		||||
                    # # # # #   . . . . .
 | 
			
		||||
                    # # # # #   . . . . .
 | 
			
		||||
                    `, 400)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(300)
 | 
			
		||||
    }
 | 
			
		||||
    waitNoButtons()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Read a value 0,1,2,3,4 from either ANALOG or TILT
 | 
			
		||||
 */
 | 
			
		||||
function readSensor(): number {
 | 
			
		||||
    let value = 0
 | 
			
		||||
    // Produce a sensor value in range 0..1023
 | 
			
		||||
    if (sensorType == "ANALOG") {
 | 
			
		||||
        // Input range is 0..1023
 | 
			
		||||
        value = pins.analogReadPin(AnalogPin.P0)
 | 
			
		||||
    } else if (sensorType == "TILT") {
 | 
			
		||||
        // Input range is -1024 (pads highest)..1023 (pads lowest)
 | 
			
		||||
        value = input.acceleration(Dimension.Y)
 | 
			
		||||
        // Emulator sometimes returns out of range values, so clamp to expected range
 | 
			
		||||
        value = Math.clamp(-1024, 1023, value)
 | 
			
		||||
        // Convert to an entirely positive range from 0 pads full up to 2047 pads full down
 | 
			
		||||
        // (hinged at the 'eyes' end)
 | 
			
		||||
        value = value + 1024
 | 
			
		||||
        // Invert the direction, so that "pads up" is largest, "pads down" is smallest
 | 
			
		||||
        value = 2047 - value
 | 
			
		||||
        // We want the same range as the analog, so halve the range
 | 
			
		||||
        value = value / 2
 | 
			
		||||
    }
 | 
			
		||||
    // 5 possible values (0,1,2,3,4) based on sensible thresholds
 | 
			
		||||
    // We do this by thresholds, so that we have more control over the 5 levels
 | 
			
		||||
    if (value < 200) {
 | 
			
		||||
        return 0
 | 
			
		||||
    } else if (value < 400) {
 | 
			
		||||
        return 1
 | 
			
		||||
    } else if (value < 600) {
 | 
			
		||||
        return 2
 | 
			
		||||
    } else if (value < 800) {
 | 
			
		||||
        return 3
 | 
			
		||||
    }
 | 
			
		||||
    return 4
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitNoButtons() {
 | 
			
		||||
    while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,529 +0,0 @@
 | 
			
		||||
let opMaxTime: number
 | 
			
		||||
let procMaxTime: number
 | 
			
		||||
let procsToDo: number
 | 
			
		||||
let recoveryTriesMax: number
 | 
			
		||||
let tenseTime: number
 | 
			
		||||
let flatlineTimeMax: number
 | 
			
		||||
let recoveryProbability: number
 | 
			
		||||
let aWasPressed: boolean
 | 
			
		||||
let bWasPressed: boolean
 | 
			
		||||
let digitsImg: Image
 | 
			
		||||
let tweezerCount_: number
 | 
			
		||||
let wasTweezers: boolean
 | 
			
		||||
let wasNose: boolean
 | 
			
		||||
let isTweezers: boolean
 | 
			
		||||
 | 
			
		||||
// P0 blue wire, tweezers (active high)
 | 
			
		||||
// P1, green wire nose button/LED (active high)
 | 
			
		||||
// P2/red speaker (not a self toned beeper, but a piezo or a speaker)
 | 
			
		||||
opMaxTime = 120 * 1000
 | 
			
		||||
procsToDo = 3
 | 
			
		||||
procMaxTime = 60 * 1000
 | 
			
		||||
tenseTime = 4000
 | 
			
		||||
flatlineTimeMax = 15 * 1000
 | 
			
		||||
recoveryTriesMax = 3
 | 
			
		||||
recoveryProbability = 60
 | 
			
		||||
let highScore = 0
 | 
			
		||||
digitsImg = images.createImage(`
 | 
			
		||||
    . . # . .   . . # . .   . # # . .   . # # . .   . # . . .   . # # # .   . . # # .   . # # # .   . . # . .   . . # . .
 | 
			
		||||
    . # . # .   . # # . .   . . . # .   . . . # .   . # . . .   . # . . .   . # . . .   . . . . .   . # . # .   . # . # .
 | 
			
		||||
    . # . # .   . . # . .   . . # . .   . . # . .   . # # # .   . . # . .   . # # . .   . . # . .   . . # . .   . . # # .
 | 
			
		||||
    . # . # .   . . # . .   . # . . .   . . . # .   . . # . .   . . . # .   . # . # .   . # . . .   . # . # .   . . . # .
 | 
			
		||||
    . . # . .   . # # # .   . # # # .   . # # . .   . . # . .   . # # . .   . . # . .   . # . . .   . . # . .   . # # . .
 | 
			
		||||
    `)
 | 
			
		||||
startIOMonitor()
 | 
			
		||||
while (true) {
 | 
			
		||||
    splashScreen()
 | 
			
		||||
    if (buttonB()) {
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            . . . . .   # # . . .   . # . . .   . # . . .   . . . # .   . . . . .
 | 
			
		||||
            . . . . #   . . . . #   # # . . #   . # . . #   . . # . #   . . . . #
 | 
			
		||||
            . . . . #   . . . . #   . . . . #   # # . . #   # # . . #   # # # # #
 | 
			
		||||
            # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
            # . . . #   # . . . #   # . . . #   # . . . #   # . . . #   # . . . #
 | 
			
		||||
            `, 400)
 | 
			
		||||
        let finalScore = surgery()
 | 
			
		||||
        if (game.score() > highScore) {
 | 
			
		||||
            basic.showString("HI", 150)
 | 
			
		||||
            highScore = finalScore
 | 
			
		||||
        }
 | 
			
		||||
        flashDigit(finalScore)
 | 
			
		||||
        waitButtonB()
 | 
			
		||||
    } else if (buttonA()) {
 | 
			
		||||
        testMode()
 | 
			
		||||
    } else {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function surgery(): number {
 | 
			
		||||
    let score = 0
 | 
			
		||||
    let speed = 150
 | 
			
		||||
    let opStartTime = input.runningTime()
 | 
			
		||||
    let procStartTime = -1
 | 
			
		||||
    let procNumber = -1
 | 
			
		||||
    let procsDone = 0
 | 
			
		||||
    let recoveryTry = 0
 | 
			
		||||
    let timer = 0
 | 
			
		||||
    let state = "CHOOSE PROC"
 | 
			
		||||
    resetButtons()
 | 
			
		||||
    while (true) {
 | 
			
		||||
        basic.pause(10)
 | 
			
		||||
        let event = getEvent(state)
 | 
			
		||||
        if (event == "CUT") {
 | 
			
		||||
            state = "ARREST"
 | 
			
		||||
        }
 | 
			
		||||
        // CHECK TIMERS
 | 
			
		||||
        if (!(procStartTime == -1)) {
 | 
			
		||||
            if (input.runningTime() - procStartTime > procMaxTime) {
 | 
			
		||||
                state = "LOST"
 | 
			
		||||
            } else {
 | 
			
		||||
                // TODO add code here to speed up near end of proc
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (input.runningTime() - opStartTime > opMaxTime) {
 | 
			
		||||
            state = "LOST"
 | 
			
		||||
        } else {
 | 
			
		||||
            // TODO add code here to speed up near end of op
 | 
			
		||||
        }
 | 
			
		||||
        // PROCESS SPECIFIC STATES
 | 
			
		||||
        if (state == "CHOOSE PROC") {
 | 
			
		||||
            if (procNumber == -1) {
 | 
			
		||||
                procNumber = 1
 | 
			
		||||
                showDigit(procNumber)
 | 
			
		||||
            } else if (event == "SCROLL") {
 | 
			
		||||
                procNumber = procNumber + 1
 | 
			
		||||
                if (procNumber > 9) {
 | 
			
		||||
                    procNumber = 1
 | 
			
		||||
                }
 | 
			
		||||
                showDigit(procNumber)
 | 
			
		||||
            } else if (event == "SELECT") {
 | 
			
		||||
                procStartTime = input.runningTime()
 | 
			
		||||
                state = "HEALTHY"
 | 
			
		||||
                speed = 100
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "HEALTHY") {
 | 
			
		||||
            speed = 100
 | 
			
		||||
            ecg(speed)
 | 
			
		||||
            if (event == "TWINGE") {
 | 
			
		||||
                state = "TENSE"
 | 
			
		||||
                timer = input.runningTime()
 | 
			
		||||
            } else if (event == "DONE") {
 | 
			
		||||
                state = "PROC DONE"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "TENSE") {
 | 
			
		||||
            speed = 25
 | 
			
		||||
            ecg(speed)
 | 
			
		||||
            if (event == "TWINGE") {
 | 
			
		||||
                state = "ARREST"
 | 
			
		||||
            } else if (input.runningTime() - timer > tenseTime) {
 | 
			
		||||
                state = "HEALTHY"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "ARREST") {
 | 
			
		||||
            timer = input.runningTime()
 | 
			
		||||
            recoveryTry = recoveryTriesMax
 | 
			
		||||
            state = "FLATLINE"
 | 
			
		||||
        } else if (state == "FLATLINE") {
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                `)
 | 
			
		||||
            beepOn()
 | 
			
		||||
            if (event == "SHOCK") {
 | 
			
		||||
                state = "SHOCKING"
 | 
			
		||||
            } else if (input.runningTime() - timer > flatlineTimeMax) {
 | 
			
		||||
                state = "LOST"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "SHOCKING") {
 | 
			
		||||
            charging()
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . #   . . . . #   . . . . .   . . . . .
 | 
			
		||||
                . . . # .   . . . # .   . . . # .   . . . . .
 | 
			
		||||
                . . . . .   . . # . .   . . # . .   . . # . .
 | 
			
		||||
                . . . . .   . . . . .   . # . . .   . # . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . # . . .
 | 
			
		||||
                `, 150)
 | 
			
		||||
            beepNTimesFor(15, 500)
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   # . . . #
 | 
			
		||||
                . . . . .   . . . . .   # . . # .   . . . . .
 | 
			
		||||
                . . . . .   # . # . .   . . . . .   . . . . .
 | 
			
		||||
                . # . . .   . # . . .   . . . . .   . . . . .
 | 
			
		||||
                . # . . .   . # . . .   . # . . .   . # . . .
 | 
			
		||||
                `, 150)
 | 
			
		||||
            state = "SHOCKED"
 | 
			
		||||
        } else if (state == "SHOCKED") {
 | 
			
		||||
            let recover = Math.random(100)
 | 
			
		||||
            if (recover >= recoveryProbability) {
 | 
			
		||||
                state = "RECOVERED"
 | 
			
		||||
            } else {
 | 
			
		||||
                state = "FAILED"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "RECOVERED") {
 | 
			
		||||
            beepOff()
 | 
			
		||||
            basic.pause(500)
 | 
			
		||||
            beep()
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . # . # .   . . . . .   . # . # .   . . . . .   . # . # .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                # . . . #   . . . . .   # . . . #   . . . . .   # . . . #
 | 
			
		||||
                . # # # .   . . . . .   . # # # .   . . . . .   . # # # .
 | 
			
		||||
                `, 400)
 | 
			
		||||
            state = "HEALTHY"
 | 
			
		||||
        } else if (state == "FAILED") {
 | 
			
		||||
            recoveryTry = recoveryTry - 1
 | 
			
		||||
            if (recoveryTry > 0) {
 | 
			
		||||
                state = "FLATLINE"
 | 
			
		||||
            } else {
 | 
			
		||||
                state = "LOST"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "PROC DONE") {
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . . . #
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . # .   . . . # .
 | 
			
		||||
                # . . . .   # . . . .   # . # . .   # . # . .   # . # . .
 | 
			
		||||
                . . . . .   . # . . .   . # . . .   . # . . .   . # . . .
 | 
			
		||||
                `, 400)
 | 
			
		||||
            score = score + pointsForProc(procNumber)
 | 
			
		||||
            procsDone = procsDone + 1
 | 
			
		||||
            procStartTime = -1
 | 
			
		||||
            if (procsDone == procsToDo) {
 | 
			
		||||
                state = "OP DONE"
 | 
			
		||||
            } else {
 | 
			
		||||
                procNumber = -1
 | 
			
		||||
                state = "CHOOSE PROC"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "OP DONE") {
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . # .   . # . . .   . . # . .   . . . # .   . . . . #   . . # . .   . . # . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . #   . . # . #   . # . . #   . . # . .   . . . # .   . . . . #   . . # . .   . . # . .   . # . . .   # . . . .   . . . . .
 | 
			
		||||
                # # # # #   # # . . #   # # . . #   . # # . .   . . # # .   . . . # #   . # # . .   . . # . .   . # . . .   # . . . .   . . . . .
 | 
			
		||||
                # # # # #   # # # # #   # # # # #   . # # # #   . . # # #   . . . # #   . . . # #   . . # # #   . # . # #   # . . # #   . . . # #
 | 
			
		||||
                # . . . #   # . . . #   # . . . #   . # . . .   . . # . .   . . . # .   . . . # .   . . . # .   . # . # .   # . . # .   . . . # .
 | 
			
		||||
                `, 400)
 | 
			
		||||
            return score
 | 
			
		||||
        } else if (state == "LOST") {
 | 
			
		||||
            beepOn()
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                `)
 | 
			
		||||
            basic.pause(3000)
 | 
			
		||||
            beepOff()
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   # # # # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . #   # # # # #   . . . . #   . . . . #   . . . . #   # . # . #   . . . . #   # . # . #   . . . . #
 | 
			
		||||
                # # # # #   . . . . #   . . . . #   . . . . #   . . . . #   . . . . #   . . . . #   . . . . #   . . . . #
 | 
			
		||||
                # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
                # . . . #   # . . . #   # . . . #   # . . . #   # . . . #   # . . . #   # . . . #   # . . . #   # . . . #
 | 
			
		||||
                `, 400)
 | 
			
		||||
            return score
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * if any button pressed, terminate the animation immediately
 | 
			
		||||
 */
 | 
			
		||||
function splashScreen() {
 | 
			
		||||
    let img = images.createImage(`
 | 
			
		||||
        . # . # .   . # . # .   . # . # .   . # . # .   . . # . .   . # # . .
 | 
			
		||||
        # # # # #   # . # . #   # # # # #   # . # . #   . # . # .   . # . # .
 | 
			
		||||
        # # # # #   # . . . #   # # # # #   # . . . #   . # . # .   . # # . .
 | 
			
		||||
        . # # # .   . # . # .   . # # # .   . # . # .   . # . # .   . # . . .
 | 
			
		||||
        . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . # . . .
 | 
			
		||||
        `)
 | 
			
		||||
    let x = 0
 | 
			
		||||
    while (!aWasPressed && !bWasPressed) {
 | 
			
		||||
        img.showImage(x)
 | 
			
		||||
        basic.pause(500)
 | 
			
		||||
        x = x + 5
 | 
			
		||||
        if (x >= img.width()) {
 | 
			
		||||
            x = 0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Test sensing and buzzing
 | 
			
		||||
 * I/O at moment is (assuming self toning beeper)
 | 
			
		||||
 * P0 is beeper and nose LED
 | 
			
		||||
 * P1 is the tweezer sense wire
 | 
			
		||||
 * P2 is possibly the nose button
 | 
			
		||||
 * If we want amplification, might have to use piezo library
 | 
			
		||||
 * which means using extra pins
 | 
			
		||||
 */
 | 
			
		||||
function testMode() {
 | 
			
		||||
    while (!(buttonA())) {
 | 
			
		||||
        if (pins.digitalReadPin(DigitalPin.P1) == 1) {
 | 
			
		||||
            pins.digitalWritePin(DigitalPin.P0, 1)
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . #
 | 
			
		||||
                . . . # .
 | 
			
		||||
                # . # . .
 | 
			
		||||
                . # . . .
 | 
			
		||||
                `)
 | 
			
		||||
        } else {
 | 
			
		||||
            pins.digitalWritePin(DigitalPin.P0, 0)
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                # # # # #
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                `)
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SENSE TWINGE/CUT FROM TWEEZERS (10ms per sample)
 | 
			
		||||
 * @param state TODO
 | 
			
		||||
 */
 | 
			
		||||
function getEvent(state: string): string {
 | 
			
		||||
    if (wasTweezers) {
 | 
			
		||||
        if (tweezerCount_ > 20) {
 | 
			
		||||
            wasTweezers = false
 | 
			
		||||
            tweezerCount_ = 0
 | 
			
		||||
            return "CUT"
 | 
			
		||||
        } else if (!isTweezers) {
 | 
			
		||||
            wasTweezers = false
 | 
			
		||||
            tweezerCount_ = 0
 | 
			
		||||
            return "TWINGE"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // SENSE A OR B BUTTON PRESSES
 | 
			
		||||
    if (state == "CHOOSE PROC") {
 | 
			
		||||
        if (buttonA()) {
 | 
			
		||||
            return "SCROLL"
 | 
			
		||||
        } else if (buttonB()) {
 | 
			
		||||
            return "SELECT"
 | 
			
		||||
        }
 | 
			
		||||
    } else if (state == "FLATLINE") {
 | 
			
		||||
        if (buttonB()) {
 | 
			
		||||
            return "SHOCK"
 | 
			
		||||
        } else if (nose()) {
 | 
			
		||||
            return "SHOCK"
 | 
			
		||||
        }
 | 
			
		||||
    } else if (state == "HEALTHY") {
 | 
			
		||||
        if (buttonB()) {
 | 
			
		||||
            return "DONE"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Clear any flags for unnecessary events in a given state to prevent latching
 | 
			
		||||
    aWasPressed = false
 | 
			
		||||
    bWasPressed = false
 | 
			
		||||
    return "NONE"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function flashDigit(digit: number) {
 | 
			
		||||
    for (let i = 0; i < 4; i++) {
 | 
			
		||||
        showDigit(digit)
 | 
			
		||||
        basic.pause(200)
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        basic.pause(200)
 | 
			
		||||
    }
 | 
			
		||||
    showDigit(digit)
 | 
			
		||||
    basic.pause(1000)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Make a short beep sound
 | 
			
		||||
 */
 | 
			
		||||
function beep() {
 | 
			
		||||
    beepOn()
 | 
			
		||||
    basic.pause(200)
 | 
			
		||||
    beepOff()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * work out score for a procedure
 | 
			
		||||
 * @param procNumber TODO
 | 
			
		||||
 */
 | 
			
		||||
function pointsForProc(procNumber: number): number {
 | 
			
		||||
    if (procNumber < 4) {
 | 
			
		||||
        return 1
 | 
			
		||||
    } else if (procNumber < 7) {
 | 
			
		||||
        return 2
 | 
			
		||||
    } else {
 | 
			
		||||
        return 3
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * beep n times, for a total duration of m
 | 
			
		||||
 * @param times TODO
 | 
			
		||||
 * @param duration TODO
 | 
			
		||||
 */
 | 
			
		||||
function beepNTimesFor(times: number, duration: number) {
 | 
			
		||||
    let halfCycle = duration / (times * 2)
 | 
			
		||||
    for (let i = 0; i < times; i++) {
 | 
			
		||||
        beepOn()
 | 
			
		||||
        basic.pause(halfCycle)
 | 
			
		||||
        beepOff()
 | 
			
		||||
        basic.pause(halfCycle)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function startIOMonitor() {
 | 
			
		||||
    aWasPressed = false
 | 
			
		||||
    input.onButtonPressed(Button.A, () => {
 | 
			
		||||
        aWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    bWasPressed = false
 | 
			
		||||
    input.onButtonPressed(Button.B, () => {
 | 
			
		||||
        bWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    wasTweezers = false
 | 
			
		||||
    isTweezers = false
 | 
			
		||||
    tweezerCount_ = 0
 | 
			
		||||
    control.inBackground(() => {
 | 
			
		||||
        let buzzCount = 0
 | 
			
		||||
        while (true) {
 | 
			
		||||
            if (pins.digitalReadPin(DigitalPin.P0) == 1) {
 | 
			
		||||
                wasTweezers = true
 | 
			
		||||
                isTweezers = true
 | 
			
		||||
                tweezerCount_ = tweezerCount_ + 1
 | 
			
		||||
                if (buzzCount == 0) {
 | 
			
		||||
                    pins.analogWritePin(AnalogPin.P2, 512)
 | 
			
		||||
                    pins.analogSetPeriod(AnalogPin.P2, 5000)
 | 
			
		||||
                }
 | 
			
		||||
                buzzCount = 10
 | 
			
		||||
            } else {
 | 
			
		||||
                isTweezers = false
 | 
			
		||||
            }
 | 
			
		||||
            if (buzzCount > 0) {
 | 
			
		||||
                buzzCount = buzzCount - 1
 | 
			
		||||
                if (buzzCount == 0) {
 | 
			
		||||
                    pins.analogWritePin(AnalogPin.P2, 0)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            basic.pause(10)
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Shows a single digit, with a nicer font than the standard micro:bit font
 | 
			
		||||
 * @param digit TODO
 | 
			
		||||
 */
 | 
			
		||||
function showDigit(digit: number) {
 | 
			
		||||
    digit = Math.clamp(0, 9, digit)
 | 
			
		||||
    digitsImg.showImage(digit * 5)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * check to see if button A was pressed recently
 | 
			
		||||
 */
 | 
			
		||||
function buttonA(): boolean {
 | 
			
		||||
    if (aWasPressed) {
 | 
			
		||||
        aWasPressed = false
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitButtonA() {
 | 
			
		||||
    while (!(buttonA())) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function buttonB(): boolean {
 | 
			
		||||
    if (bWasPressed) {
 | 
			
		||||
        bWasPressed = false
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitButtonB() {
 | 
			
		||||
    while (!(buttonB())) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function beepOn() {
 | 
			
		||||
    pins.analogWritePin(AnalogPin.P2, 512)
 | 
			
		||||
    pins.analogSetPeriod(AnalogPin.P2, 2272)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function beepOff() {
 | 
			
		||||
    pins.analogWritePin(AnalogPin.P2, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function resetButtons() {
 | 
			
		||||
    aWasPressed = false
 | 
			
		||||
    bWasPressed = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ecg(speed: number) {
 | 
			
		||||
    beepOn()
 | 
			
		||||
    pins.digitalWritePin(DigitalPin.P1, 1)
 | 
			
		||||
    basic.pause(50)
 | 
			
		||||
    beepOff()
 | 
			
		||||
    basic.showAnimation(`
 | 
			
		||||
        . . . . #   . . . # .   . . # . .   . # . . .   # . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . #   . . . # .   . . # . .   . # . . .   # . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . #   . . . # .   . . # . .   . # . . .   # . . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . #   . . . # #   . . # # .   . # # . .   # # . . .   # . . . .   . . . . .
 | 
			
		||||
        # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
        `, speed)
 | 
			
		||||
    pins.digitalWritePin(DigitalPin.P1, 0)
 | 
			
		||||
    basic.pause(speed * 10)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function nose(): boolean {
 | 
			
		||||
    if (wasNose) {
 | 
			
		||||
        wasNose = false
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * start period in microseconds
 | 
			
		||||
 */
 | 
			
		||||
function charging() {
 | 
			
		||||
    let period = 2000
 | 
			
		||||
    let dec = 500
 | 
			
		||||
    pins.analogWritePin(AnalogPin.P2, 512)
 | 
			
		||||
    pins.analogSetPeriod(AnalogPin.P2, period)
 | 
			
		||||
    basic.showLeds(`
 | 
			
		||||
        . # # . .
 | 
			
		||||
        . . . # .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . . . # .
 | 
			
		||||
        . # # . .
 | 
			
		||||
        `)
 | 
			
		||||
    basic.pause(500)
 | 
			
		||||
    pins.analogSetPeriod(AnalogPin.P2, period - dec)
 | 
			
		||||
    basic.showLeds(`
 | 
			
		||||
        . # # . .
 | 
			
		||||
        . . . # .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . # . . .
 | 
			
		||||
        . # # # .
 | 
			
		||||
        `)
 | 
			
		||||
    basic.pause(500)
 | 
			
		||||
    pins.analogSetPeriod(AnalogPin.P2, period - dec * 2)
 | 
			
		||||
    basic.showLeds(`
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . # # . .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . # # # .
 | 
			
		||||
        `)
 | 
			
		||||
    basic.pause(500)
 | 
			
		||||
    beepOff()
 | 
			
		||||
}
 | 
			
		||||
@@ -1,178 +0,0 @@
 | 
			
		||||
let wasShake: boolean
 | 
			
		||||
 | 
			
		||||
input.onShake(() => {
 | 
			
		||||
    wasShake = true
 | 
			
		||||
})
 | 
			
		||||
wait_6Hours()
 | 
			
		||||
timeForTest()
 | 
			
		||||
alertnessTest()
 | 
			
		||||
wait_2Hours()
 | 
			
		||||
timeForTest()
 | 
			
		||||
alertnessTest()
 | 
			
		||||
wait_2Hours()
 | 
			
		||||
timeForTest()
 | 
			
		||||
alertnessTest()
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * animate back to work
 | 
			
		||||
 * animate take a rest
 | 
			
		||||
 */
 | 
			
		||||
function animations() { }
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * wait 6 hours
 | 
			
		||||
 * because this is a test program, we only wait for a short time
 | 
			
		||||
 */
 | 
			
		||||
function wait_6Hours() {
 | 
			
		||||
    basic.showAnimation(`
 | 
			
		||||
        . . # . .   . . . . #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .
 | 
			
		||||
        . . # . .   . . . # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . # . . .
 | 
			
		||||
        . . # . .   . . # . .   . . # # #   . . # . .   . . # . .   . . # . .   # # # . .   . . # . .
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . # .   . . # . .   . # . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . #   . . # . .   # . . . .   . . . . .   . . . . .
 | 
			
		||||
        `, 500)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * wait for 2 hours
 | 
			
		||||
 * because this is test code, we only wait a few seconds
 | 
			
		||||
 */
 | 
			
		||||
function wait_2Hours() {
 | 
			
		||||
    basic.showAnimation(`
 | 
			
		||||
        . . # . .   . . . . #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .
 | 
			
		||||
        . . # . .   . . . # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . # . . .
 | 
			
		||||
        . . # . .   . . # . .   . . # # #   . . # . .   . . # . .   . . # . .   # # # . .   . . # . .
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . # .   . . # . .   . # . . .   . . . . .   . . . . .
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . #   . . # . .   # . . . .   . . . . .   . . . . .
 | 
			
		||||
        `, 500)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function alertnessTest() {
 | 
			
		||||
    let goodResponse = 1000
 | 
			
		||||
    let threshold = 5
 | 
			
		||||
    let score = 0
 | 
			
		||||
    // Start test on button press
 | 
			
		||||
    let x = 0
 | 
			
		||||
    let start = images.createImage(`
 | 
			
		||||
        . . # . .   . . # . .
 | 
			
		||||
        . . # . .   . # . # .
 | 
			
		||||
        . . # . .   . . . # .
 | 
			
		||||
        . . . . .   . . # . .
 | 
			
		||||
        . . # . .   . . # . .
 | 
			
		||||
        `)
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        start.showImage(x)
 | 
			
		||||
        x = x + 5
 | 
			
		||||
        if (x >= start.width()) {
 | 
			
		||||
            x = 0
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(300)
 | 
			
		||||
    }
 | 
			
		||||
    // Wait for button(s) to be released
 | 
			
		||||
    while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
    // Run 10 random cognition response tests
 | 
			
		||||
    for (let i = 0; i < 9; i++) {
 | 
			
		||||
        // Choose random delay and random outcome
 | 
			
		||||
        let delay = Math.random(5) + 5
 | 
			
		||||
        let outcome = Math.random(2)
 | 
			
		||||
        // Draw moving dots on screen until delay expires
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        for (let j = 0; j < delay; j++) {
 | 
			
		||||
            led.plot(j % 5, 2)
 | 
			
		||||
            basic.pause(200)
 | 
			
		||||
            basic.clearScreen()
 | 
			
		||||
        }
 | 
			
		||||
        // Show shake or button icon
 | 
			
		||||
        if (outcome == 0) {
 | 
			
		||||
            // Press the button!
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . # # # .
 | 
			
		||||
                . # # # .
 | 
			
		||||
                . # # # .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                `)
 | 
			
		||||
        } else {
 | 
			
		||||
            // Shake the bit!
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                # . # . .
 | 
			
		||||
                # . . # .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                # . . # .
 | 
			
		||||
                # . # . .
 | 
			
		||||
                `)
 | 
			
		||||
        }
 | 
			
		||||
        // Wait up to 3 seconds for button, shake, or timeout
 | 
			
		||||
        wasShake = false
 | 
			
		||||
        let timer = input.runningTime()
 | 
			
		||||
        let timeout = 3000
 | 
			
		||||
        while (input.runningTime() < timer + timeout) {
 | 
			
		||||
            if (wasShake) {
 | 
			
		||||
                break
 | 
			
		||||
            } else if (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
                break
 | 
			
		||||
            } else {
 | 
			
		||||
                basic.pause(100)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Assess the response and the response time
 | 
			
		||||
        let response = input.runningTime() - timer
 | 
			
		||||
        if (outcome == 0 && input.buttonIsPressed(Button.B) && response <= goodResponse) {
 | 
			
		||||
            score = score + 1
 | 
			
		||||
        } else if (outcome == 1 && wasShake && response <= goodResponse) {
 | 
			
		||||
            score = score + 1
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Show final score flashing 5 times (0..9)
 | 
			
		||||
    for (let k = 0; k < 5; k++) {
 | 
			
		||||
        basic.showNumber(score, 0)
 | 
			
		||||
        basic.pause(250)
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        basic.pause(250)
 | 
			
		||||
    }
 | 
			
		||||
    basic.showNumber(score, 0)
 | 
			
		||||
    basic.pause(500)
 | 
			
		||||
    if (score < threshold) {
 | 
			
		||||
        // Time for a break, show coffee cup animation
 | 
			
		||||
        for (let l = 0; l < 3; l++) {
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . # . . .   . # . . .   . . . . .   . . # . .   . . # . .   . . . . .
 | 
			
		||||
                . . . . .   . # . . .   . # . . .   . . . . .   . . # . .   . . # . .   . . . . .   . . . . .
 | 
			
		||||
                # . . # .   # # . # .   # . . # .   # . . # .   # . # # .   # . . # .   # . . # .   # . . # .
 | 
			
		||||
                # . . # #   # . . # #   # . . # #   # . . # #   # . . # #   # . . # #   # . . # #   # . . # #
 | 
			
		||||
                # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .
 | 
			
		||||
                `, 400)
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // All ok, back to work, show digging animation
 | 
			
		||||
        for (let m = 0; m < 3; m++) {
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                # . # . .   # . . . .   # . . . .
 | 
			
		||||
                . # # . .   . # . # .   . # . . .
 | 
			
		||||
                # # # . .   . . # # .   . . # . #
 | 
			
		||||
                . . . . .   . # # # .   . . . # #
 | 
			
		||||
                . . . . .   . . . . .   . . # # #
 | 
			
		||||
                `, 400)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Wait for any button press to finish test
 | 
			
		||||
    while (!input.buttonIsPressed(Button.A) && !input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * alert the user it is time to take the test
 | 
			
		||||
 * in a real system, this might give them 5 1 minute warnings
 | 
			
		||||
 */
 | 
			
		||||
function timeForTest() {
 | 
			
		||||
    basic.showAnimation(`
 | 
			
		||||
        . # # # .   . # . . .   . # # . .   . # # . .   . . # . .
 | 
			
		||||
        . # . . .   . # . . .   . . . # .   . . . # .   . # # . .
 | 
			
		||||
        . . # . .   . # # # .   . # # . .   . . # . .   . . # . .
 | 
			
		||||
        . . . # .   . . # . .   . . . # .   . # . . .   . . # . .
 | 
			
		||||
        . # # . .   . . # . .   . # # . .   . # # # .   . # # # .
 | 
			
		||||
        `, 700)
 | 
			
		||||
}
 | 
			
		||||
@@ -1,157 +0,0 @@
 | 
			
		||||
let maxGameTime: number
 | 
			
		||||
let wasShake: boolean
 | 
			
		||||
 | 
			
		||||
maxGameTime = 60000
 | 
			
		||||
input.onShake(() => {
 | 
			
		||||
    wasShake = true
 | 
			
		||||
})
 | 
			
		||||
while (true) {
 | 
			
		||||
    splashScreen()
 | 
			
		||||
    if (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # . .   # # # # #
 | 
			
		||||
            # # # . .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # . .   # . . . .   # . . . .   # . . . .   # . . . .   # # # # #   # # # # #
 | 
			
		||||
            # # # . .   # # # . .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # . .   # # # . .   # # # . .   # # # # #   # # # # #   # # # # #
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . . . # .   . . . # .   . . . # .   . . . # .   . . . # .   . . . # .   . . . # #   . . # # #   . # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . . . . .   . . . # .   . . . # #   . . # # #   . # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
            `, 400)
 | 
			
		||||
        let score = playOneGame()
 | 
			
		||||
        flashDigit(score, 5)
 | 
			
		||||
        waitButtonB()
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            # # # # #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            # # # # #   # # # # #   . . . . .   . . . . .   . . . . .   . . . . .   . # . # .   . . . . .   . # . # .   . . . . .
 | 
			
		||||
            # # # # #   # # # # #   # # # # #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            # # # # #   # # # # #   # # # # #   # # # # #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            `, 400)
 | 
			
		||||
    } else if (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        calibrate()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function playOneGame(): number {
 | 
			
		||||
    let countDots = 0
 | 
			
		||||
    let x = 2
 | 
			
		||||
    let y = 2
 | 
			
		||||
    let xdir = true
 | 
			
		||||
    let canvas = images.createImage(`
 | 
			
		||||
        . . . . .
 | 
			
		||||
        . . . . .
 | 
			
		||||
        . . . . .
 | 
			
		||||
        . . . . .
 | 
			
		||||
        . . . . .
 | 
			
		||||
        `)
 | 
			
		||||
    wasShake = false
 | 
			
		||||
    let bearing = input.compassHeading()
 | 
			
		||||
    let startTime = input.runningTime()
 | 
			
		||||
    while (countDots < 25 && input.runningTime() - startTime < maxGameTime) {
 | 
			
		||||
        if (wasShake) {
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . # # # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . # # # .   . . # . .   . # # # .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . # # # .   . . # . .   . . # . .   . . # . .   . # # # .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . # # # .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . # # # .   . . . . .   . . . . .
 | 
			
		||||
                . # # # .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . # # # .   . . . . .
 | 
			
		||||
                `, 50)
 | 
			
		||||
            let pos = Math.random(5)
 | 
			
		||||
            if (xdir) {
 | 
			
		||||
                if (!canvas.pixel(pos, y)) {
 | 
			
		||||
                    canvas.setPixel(pos, y, true)
 | 
			
		||||
                    countDots = countDots + 1
 | 
			
		||||
                }
 | 
			
		||||
            } else if (!canvas.pixel(x, pos)) {
 | 
			
		||||
                canvas.setPixel(x, pos, true)
 | 
			
		||||
                countDots = countDots + 1
 | 
			
		||||
            }
 | 
			
		||||
            wasShake = false
 | 
			
		||||
            canvas.showImage(0)
 | 
			
		||||
        } else if (Math.abs(input.compassHeading() - bearing) > 60) {
 | 
			
		||||
            xdir = !xdir
 | 
			
		||||
            bearing = input.compassHeading()
 | 
			
		||||
            if (xdir) {
 | 
			
		||||
                x = Math.random(5)
 | 
			
		||||
            } else {
 | 
			
		||||
                y = Math.random(5)
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            basic.pause(100)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return dotsToScore(countDots)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function splashScreen() {
 | 
			
		||||
    let img = images.createImage(`
 | 
			
		||||
        # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   . # # # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . # .   . . # # .   . # # # .   # # # # .   # # # # .   . # # # .   . . # # .   . . . # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .
 | 
			
		||||
        # . . . #   # . . . #   # . . . #   # . . . #   # . . . #   . # # # .   . . # . .   . # # # .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   . # . . .   . . # . .   . . . # .   . . . . #   . . . # #   . . # . #   . # . . #   # . . . #   # . . . #   # . . . #   # . . . #   . # . . #   . . # . #   . . . # #   . . . . #   . . . # .   . . # . .   . # . . .   # . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . # # # .   . . # . .   . # # # .   # . . . #   # . . . #   # . . . #   # . . . #
 | 
			
		||||
        # # # # .   # # # # .   # # # # .   # # # # .   . # # # .   . . # . .   . . # . .   . . # . .   . # # # .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # .   # # # # #   # # # # .   # # # . .   # # . . .   # . . . .   . . . . .   . . . . .   . . . . .   . # # # .   . . # . .   . . # . .   . . # . .   . # # # .   # # # # .   # # # # .   # # # # .
 | 
			
		||||
        # . . . .   # . . . .   # . . . .   . # # # .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . # # # .   . . . . .   . . . . .   # . . . .   . # . . .   . . # . .   . . . # .   . . . . #   . . . # .   . . # # .   . # . # .   # . . # .   # . . # .   # . . # .   # . . # .   . # . # .   . . # # .   . . . # .   . . . . #   . . . # .   . . # . .   . # . . .   # . . . .   . . . . .   . . . . .   . # # # .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . # # # .   # . . . .   # . . . .
 | 
			
		||||
        # . . . .   # . . . .   . # # # .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . # # # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . #   . . . . #   . . . . #   . . . . #   # . . . #   # . . . #   . . . . #   . . . . #   . . . . #   . . . . #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . # # # .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . . # . .   . # # # .   # . . . .
 | 
			
		||||
        `)
 | 
			
		||||
    let x = 0
 | 
			
		||||
    while (!input.buttonIsPressed(Button.A) && !input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        img.showImage(x)
 | 
			
		||||
        basic.pause(200)
 | 
			
		||||
        x = x + 5
 | 
			
		||||
        if (x >= img.width()) {
 | 
			
		||||
            x = 0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * rotate canvas
 | 
			
		||||
 */
 | 
			
		||||
function rotateImage() { }
 | 
			
		||||
 | 
			
		||||
function flashDigit(digit: number, times: number) {
 | 
			
		||||
    for (let i = 0; i < times; i++) {
 | 
			
		||||
        basic.showNumber(digit, 0)
 | 
			
		||||
        basic.pause(500)
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        basic.pause(500)
 | 
			
		||||
    }
 | 
			
		||||
    basic.showNumber(digit, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitButtonB() {
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function dotsToScore(dots: number): number {
 | 
			
		||||
    if (dots == 25) {
 | 
			
		||||
        return 9
 | 
			
		||||
    } else if (dots >= 22) {
 | 
			
		||||
        return 8
 | 
			
		||||
    } else if (dots >= 19) {
 | 
			
		||||
        return 7
 | 
			
		||||
    } else if (dots >= 16) {
 | 
			
		||||
        return 6
 | 
			
		||||
    } else if (dots >= 13) {
 | 
			
		||||
        return 5
 | 
			
		||||
    } else if (dots >= 10) {
 | 
			
		||||
        return 4
 | 
			
		||||
    } else if (dots >= 7) {
 | 
			
		||||
        return 3
 | 
			
		||||
    } else if (dots >= 4) {
 | 
			
		||||
        return 2
 | 
			
		||||
    } else if (dots >= 1) {
 | 
			
		||||
        return 1
 | 
			
		||||
    } else {
 | 
			
		||||
        return 0
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function calibrate() {
 | 
			
		||||
    basic.showString("CAL", 150)
 | 
			
		||||
    if (input.compassHeading() == -4) {
 | 
			
		||||
        input.calibrate()
 | 
			
		||||
    }
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        let h = input.compassHeading()
 | 
			
		||||
        basic.showNumber(h, 150)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,267 +0,0 @@
 | 
			
		||||
let state: string
 | 
			
		||||
let timer: number
 | 
			
		||||
let gesturesRunning: boolean
 | 
			
		||||
let wasShake: boolean
 | 
			
		||||
let wasLogoUp: boolean
 | 
			
		||||
let wasLogoDown: boolean
 | 
			
		||||
let wasScreenUp: boolean
 | 
			
		||||
let wasScreenDown: boolean
 | 
			
		||||
 | 
			
		||||
while (true) {
 | 
			
		||||
    splashScreen()
 | 
			
		||||
    if (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        // animate: add pancake
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            # # # # #   # . . . #   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            . . . . .   . # # # .   . # # # .   . . . . .   . . . . .
 | 
			
		||||
            . . . . .   . . . . .   # . . . #   # . . . #   . . . . .
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . # # # .   . # # # .
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . . . . .   # . . . #
 | 
			
		||||
            `, 250)
 | 
			
		||||
        runGameOnce()
 | 
			
		||||
        // animate: pancake done
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . # # # .   # # # # #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . . . . .   # . . . #   # # # # #   # . . . #   . . . . .   . . . . .   . # . # .   . . . . .   . # . # .   . . . . .
 | 
			
		||||
            . . . . .   . . . . .   . # # # .   # # # # #   . # # # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            # . . . #   # # # # #   # . . . #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            . # # # .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            `, 250)
 | 
			
		||||
    } else if (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        testShake()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Runs one complete game from start to end
 | 
			
		||||
 */
 | 
			
		||||
function runGameOnce() {
 | 
			
		||||
    let score = 0
 | 
			
		||||
    let cooks = 0
 | 
			
		||||
    let target_time = 0
 | 
			
		||||
    // make sure no gestures are outstanding from last game
 | 
			
		||||
    wasShake = false
 | 
			
		||||
    wasLogoUp = false
 | 
			
		||||
    wasLogoDown = false
 | 
			
		||||
    wasScreenUp = false
 | 
			
		||||
    wasScreenDown = false
 | 
			
		||||
    state = "NEWSIDE"
 | 
			
		||||
    while (true) {
 | 
			
		||||
        // Handle any gestures that can happen at any time
 | 
			
		||||
        let gesture = getGesture()
 | 
			
		||||
        if (gesture == "FLOOR") {
 | 
			
		||||
            state = "DROPPED"
 | 
			
		||||
        }
 | 
			
		||||
        // Run code appropriate to the present state of the game
 | 
			
		||||
        if (state == "NEWSIDE") {
 | 
			
		||||
            target_time = 5 + Math.random(5)
 | 
			
		||||
            state = "COOKING"
 | 
			
		||||
            startTimer()
 | 
			
		||||
        } else if (state == "COOKING") {
 | 
			
		||||
            // animate: cooking
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   # . . . .   . . . . .   . . . . #
 | 
			
		||||
                # # # # #   . # # # #   # # # # #   # # # # .
 | 
			
		||||
                `, 100)
 | 
			
		||||
 | 
			
		||||
            if (gesture == "FLIP") {
 | 
			
		||||
                state = "FLIPPING"
 | 
			
		||||
            } else if (getTimerSec() >= target_time) {
 | 
			
		||||
                state = "READY"
 | 
			
		||||
                score = score + 1
 | 
			
		||||
                startTimer()
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "READY") {
 | 
			
		||||
            // animate: ready
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # . . . #
 | 
			
		||||
                . # # # .
 | 
			
		||||
                `, 100)
 | 
			
		||||
            if (getTimerSec() > 2) {
 | 
			
		||||
                state = "BURNING"
 | 
			
		||||
                score = score - 1
 | 
			
		||||
                startTimer()
 | 
			
		||||
            } else if (gesture == "FLIP") {
 | 
			
		||||
                state = "FLIPPING"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "BURNING") {
 | 
			
		||||
            // animate: burning
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . # .   . . . # .
 | 
			
		||||
                . . . . .   . . . # .   . # . # .   . # . . .
 | 
			
		||||
                . . . . .   . # . # .   . # . . .   . . . . .
 | 
			
		||||
                . . . . .   . # . . .   . . . . .   . . . . .
 | 
			
		||||
                # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
                `, 100)
 | 
			
		||||
            if (gesture == "SKY") {
 | 
			
		||||
                state = "NEWSIDE"
 | 
			
		||||
            } else if (getTimerSec() > 2) {
 | 
			
		||||
                state = "BURNT"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "FLIPPING") {
 | 
			
		||||
            // animate: flipping
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   . . . . .   . . . . #   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   # # # # #   . # # . .   . # # # .   . . # # .   # # # # #   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   # # # # #   . . . . .   . . . # #   . # # # .   # # . . .   . . . . .   # # # # #   . . . . .
 | 
			
		||||
                . . . . .   # # # # #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # # # # #
 | 
			
		||||
                # # # # #   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                `, 100)
 | 
			
		||||
            // Prevent a spurious double-flip from happening
 | 
			
		||||
            wasShake = false
 | 
			
		||||
            cooks = cooks + 1
 | 
			
		||||
            if (cooks == 5) {
 | 
			
		||||
                state = "GAMEOVER"
 | 
			
		||||
            } else {
 | 
			
		||||
                state = "NEWSIDE"
 | 
			
		||||
            }
 | 
			
		||||
        } else if (state == "DROPPED") {
 | 
			
		||||
            // animate: dropped
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                # . . . #   . . . . .   # . . . #   . . . . .
 | 
			
		||||
                . # . # .   . . . . .   . # . # .   . . . . .
 | 
			
		||||
                . . # . .   . . . . .   . . # . .   . . . . .
 | 
			
		||||
                . # . # .   . . . . .   . # . # .   . . . . .
 | 
			
		||||
                # . . . #   . . . . .   # . . . #   . . . . .
 | 
			
		||||
                `, 250)
 | 
			
		||||
            score = 0
 | 
			
		||||
            state = "GAMEOVER"
 | 
			
		||||
        } else if (state == "BURNT") {
 | 
			
		||||
            // animate: burnt
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . . # . .   . . . . .   . # . # .   . . . . .   . # # # .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . # . .   . . . . .   . # . # .   . . . . .   . # # # .   . . . . .
 | 
			
		||||
                . . . . .   . . . . .   . . . . .   . . . . .   . # . # .   . . . . .   . # # # .   . . . . .   . . . . .
 | 
			
		||||
                . . . . .   . # . # .   . # # # .   . # . # .   . . . . .   . # # # .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                # # # # #   . # # # .   . # # # .   . # # # .   . # # # .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
                `, 250)
 | 
			
		||||
            score = 0
 | 
			
		||||
            state = "GAMEOVER"
 | 
			
		||||
        } else if (state == "GAMEOVER") {
 | 
			
		||||
            animateScore(score)
 | 
			
		||||
            state = "WAITEJECT"
 | 
			
		||||
        } else if (state == "WAITEJECT") {
 | 
			
		||||
            if (gesture == "UPSIDEDOWN") {
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * show score (0..9) flashing
 | 
			
		||||
 * @param score TODO
 | 
			
		||||
 */
 | 
			
		||||
function animateScore(score: number) {
 | 
			
		||||
    score = Math.clamp(0, 9, score)
 | 
			
		||||
    for (let i = 0; i < 5; i++) {
 | 
			
		||||
        basic.showNumber(score, 0)
 | 
			
		||||
        basic.pause(500)
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        basic.pause(500)
 | 
			
		||||
    }
 | 
			
		||||
    basic.showNumber(score, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * NOTE: Eventually this will move into a gesture library
 | 
			
		||||
 * It hides all the nasty detail of detecting gestures
 | 
			
		||||
 */
 | 
			
		||||
function getGesture(): string {
 | 
			
		||||
    if (!gesturesRunning) {
 | 
			
		||||
        input.onShake(() => {
 | 
			
		||||
            wasShake = true
 | 
			
		||||
        })
 | 
			
		||||
        input.onLogoUp(() => {
 | 
			
		||||
            wasLogoUp = true
 | 
			
		||||
        })
 | 
			
		||||
        input.onLogoDown(() => {
 | 
			
		||||
            wasLogoDown = true
 | 
			
		||||
        })
 | 
			
		||||
        input.onScreenUp(() => {
 | 
			
		||||
            wasScreenUp = true
 | 
			
		||||
        })
 | 
			
		||||
        input.onScreenDown(() => {
 | 
			
		||||
            wasScreenDown = true
 | 
			
		||||
        })
 | 
			
		||||
        gesturesRunning = true
 | 
			
		||||
    }
 | 
			
		||||
    // work out which of a possible set of gestures has occurred:
 | 
			
		||||
    // Button gestures and movement gestures both handled
 | 
			
		||||
    // This is so that it is easy to also use this on the simulator too
 | 
			
		||||
    // Generally, B is used for normal OK, A is used for abnormal RECOVERY
 | 
			
		||||
    // (flip is a normal action, touch sky to turn off smoke alarm is recovery)
 | 
			
		||||
    let a = input.buttonIsPressed(Button.A)
 | 
			
		||||
    let b = input.buttonIsPressed(Button.B)
 | 
			
		||||
    if (state == "COOKING" || state == "READY") {
 | 
			
		||||
        if (b || wasShake) {
 | 
			
		||||
            wasShake = false
 | 
			
		||||
            return "FLIP"
 | 
			
		||||
        }
 | 
			
		||||
    } else if (state == "FLIPPING") {
 | 
			
		||||
        if (a || wasLogoDown) {
 | 
			
		||||
            wasLogoDown = false
 | 
			
		||||
            return "FLOOR"
 | 
			
		||||
        }
 | 
			
		||||
    } else if (state == "BURNING") {
 | 
			
		||||
        if (a || wasLogoUp) {
 | 
			
		||||
            wasLogoUp = false
 | 
			
		||||
            return "SKY"
 | 
			
		||||
        }
 | 
			
		||||
    } else if (state == "GAMEOVER" || state == "WAITEJECT") {
 | 
			
		||||
        if (b || wasScreenDown) {
 | 
			
		||||
            wasScreenDown = false
 | 
			
		||||
            return "UPSIDEDOWN"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return "NONE"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * start timer by sampling runningtime and storing into starttime
 | 
			
		||||
 */
 | 
			
		||||
function startTimer() {
 | 
			
		||||
    timer = input.runningTime()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * get the elapsed time from the global starttime with ref to running time
 | 
			
		||||
 * in seconds.
 | 
			
		||||
 */
 | 
			
		||||
function getTimerSec(): number {
 | 
			
		||||
    let t = (input.runningTime() - timer) / 1000
 | 
			
		||||
    return t
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Show a splash screen "Perfect Pancakes >>>"
 | 
			
		||||
 * Splash screen "PP" with little arrow pointing to the start button
 | 
			
		||||
 */
 | 
			
		||||
function splashScreen() {
 | 
			
		||||
    let splash = images.createImage(`
 | 
			
		||||
        # # # # .   . . . . .   # # # # .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        # . . . #   . . . . .   # . . . #   # . . . .   . # . . .   . . # . .   . . . # .
 | 
			
		||||
        # # # # .   . . . . .   # # # # .   . # . . .   . . # . .   . . . # .   . . . . #
 | 
			
		||||
        # . . . .   . . . . .   # . . . .   # . . . .   . # . . .   . . # . .   . . . # .
 | 
			
		||||
        # . . . .   . . . . .   # . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        `)
 | 
			
		||||
    // use show image (not show animation) so that button press is more responsive
 | 
			
		||||
    let index = 0
 | 
			
		||||
    // Any button press finishes the splash screen
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B) && !input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        splash.showImage(index * 5)
 | 
			
		||||
        index = index + 1
 | 
			
		||||
        if (index > splash.width() / 5) {
 | 
			
		||||
            index = 0
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(250)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testShake() { }
 | 
			
		||||
@@ -1,242 +0,0 @@
 | 
			
		||||
let sugarThreshold: number
 | 
			
		||||
let ketoneThreshold: number
 | 
			
		||||
 | 
			
		||||
// Important parameters
 | 
			
		||||
sugarThreshold = 14
 | 
			
		||||
ketoneThreshold = 6
 | 
			
		||||
while (true) {
 | 
			
		||||
    // splash screen sugar cube (just the right sugar)
 | 
			
		||||
    basic.showAnimation(`
 | 
			
		||||
        # # # . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
        # # # . .   . # # # .   . . . . .   . . . . .
 | 
			
		||||
        # # # . .   . # # # .   . . # # #   . . # # #
 | 
			
		||||
        . . . . .   . # # # .   . . # # #   . . # # #
 | 
			
		||||
        . . . . .   . . . . .   . . # # #   . . # # #
 | 
			
		||||
        `, 400)
 | 
			
		||||
    // ask questions and give advice
 | 
			
		||||
    quiz()
 | 
			
		||||
    // wait for button press before restart
 | 
			
		||||
    waitAnyButton()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getSugar(): string {
 | 
			
		||||
    waitNoButtons()
 | 
			
		||||
    let selection = "MID"
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        // high, low, normal?
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            . . . . .   # . # . .   . . # . .
 | 
			
		||||
            . # # # .   # . # . .   . # . # .
 | 
			
		||||
            . # # # .   # . # # #   . . . # .
 | 
			
		||||
            . # # # .   # . . # .   . . # . .
 | 
			
		||||
            . . . . .   # . . # .   . . # . .
 | 
			
		||||
            `, 400)
 | 
			
		||||
        // show low, mid, or high as a bar
 | 
			
		||||
        selection = getLowMidHigh(selection)
 | 
			
		||||
    }
 | 
			
		||||
    return selection
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getKetone(): string {
 | 
			
		||||
    waitNoButtons()
 | 
			
		||||
    let selection = "MID"
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        // high, low, normal?
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            . . . . .   . . . # .   . . # . .
 | 
			
		||||
            # # . . .   . . # . .   . # . # .
 | 
			
		||||
            # # # # #   . . # # .   . . . # .
 | 
			
		||||
            # # . . #   . . # . #   . . # . .
 | 
			
		||||
            . . . . .   # . . # .   . . # . .
 | 
			
		||||
            `, 400)
 | 
			
		||||
        // show low, mid, or high as a bar
 | 
			
		||||
        selection = getLowMidHigh(selection)
 | 
			
		||||
    }
 | 
			
		||||
    return selection
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getIll(): boolean {
 | 
			
		||||
    waitNoButtons()
 | 
			
		||||
    let selection = false
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        // ask question 'happy or sad'
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            . . . . .   . . . . .   . . # . .   . . # . .
 | 
			
		||||
            . # . # .   . # . # .   . # . # .   . # . # .
 | 
			
		||||
            . . . . .   . . . . .   . . . # .   . . . # .
 | 
			
		||||
            # . . . #   . # # # .   . . # . .   . . # . .
 | 
			
		||||
            . # # # .   # . . . #   . . # . .   . . # . .
 | 
			
		||||
            `, 400)
 | 
			
		||||
        // get answer from user
 | 
			
		||||
        selection = getHappySad(selection)
 | 
			
		||||
    }
 | 
			
		||||
    // if we are happy, we are not ill
 | 
			
		||||
    return !selection
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getLowMidHigh(selection: string): string {
 | 
			
		||||
    let timeout = 2000
 | 
			
		||||
    let timer = input.runningTime()
 | 
			
		||||
    while (true) {
 | 
			
		||||
        // show the present level as a line
 | 
			
		||||
        if (selection == "LOW") {
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                `)
 | 
			
		||||
        } else if (selection == "HIGH") {
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                # # # # #
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                `)
 | 
			
		||||
        } else {
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                `)
 | 
			
		||||
        }
 | 
			
		||||
        // process any user input
 | 
			
		||||
        if (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
            // cycle round the 3 possible levels
 | 
			
		||||
            if (selection == "LOW") {
 | 
			
		||||
                selection = "MID"
 | 
			
		||||
            } else if (selection == "MID") {
 | 
			
		||||
                selection = "HIGH"
 | 
			
		||||
            } else {
 | 
			
		||||
                selection = "LOW"
 | 
			
		||||
            }
 | 
			
		||||
            // This is the 'hold repeat' time if you hold the A button
 | 
			
		||||
            basic.pause(300)
 | 
			
		||||
            // restart timer, 2 seconds of inactivity before return to main
 | 
			
		||||
            timer = input.runningTime()
 | 
			
		||||
        } else if (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
            // user is selecting so better return quickly
 | 
			
		||||
            return selection
 | 
			
		||||
        } else if (input.runningTime() > timer + timeout) {
 | 
			
		||||
            // timeout, so return to main to re-prompt user
 | 
			
		||||
            return selection
 | 
			
		||||
        } else {
 | 
			
		||||
            // This slows the loop down to stop the emulator being busy
 | 
			
		||||
            // and also preserves battery life on the micro:bit
 | 
			
		||||
            // it also affects the worst case response time
 | 
			
		||||
            // it also affects the response time
 | 
			
		||||
            basic.pause(100)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Wait for all buttons to be released
 | 
			
		||||
 * This prevents spurious selection in next question
 | 
			
		||||
 */
 | 
			
		||||
function waitNoButtons() {
 | 
			
		||||
    while (input.buttonIsPressed(Button.A) || input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getHappySad(selection: boolean): boolean {
 | 
			
		||||
    let timeout = 2000
 | 
			
		||||
    let timer = input.runningTime()
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        // Show present selection
 | 
			
		||||
        if (selection) {
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # . . . #
 | 
			
		||||
                . # # # .
 | 
			
		||||
                `)
 | 
			
		||||
        } else {
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . # # # .
 | 
			
		||||
                # . . . #
 | 
			
		||||
                `)
 | 
			
		||||
        }
 | 
			
		||||
        // Wait for any change in the selection
 | 
			
		||||
        if (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
            selection = !selection
 | 
			
		||||
            // This is the repeat time if button A held down
 | 
			
		||||
            basic.pause(500)
 | 
			
		||||
            timer = input.runningTime()
 | 
			
		||||
        } else if (input.runningTime() > timer + timeout) {
 | 
			
		||||
            return selection
 | 
			
		||||
        } else {
 | 
			
		||||
            // Preserve battery life on micro:bit and prevent emulator being busy
 | 
			
		||||
            // This is also the response time to a button press
 | 
			
		||||
            basic.pause(100)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return selection
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Button A changes value, Button B selects value
 | 
			
		||||
 */
 | 
			
		||||
function quiz() {
 | 
			
		||||
    let sugar = getSugar()
 | 
			
		||||
    if (sugar != "HIGH") {
 | 
			
		||||
        // All is ok (tick)
 | 
			
		||||
        basic.showAnimation(`
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . . . . .   . . . . .
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . . . . .   . . . . #
 | 
			
		||||
            . . . . .   . . . . .   . . . . .   . . . # .   . . . # .
 | 
			
		||||
            # . . . .   # . . . .   # . # . .   # . # . .   # . # . .
 | 
			
		||||
            . . . . .   . # . . .   . # . . .   . # . . .   . # . . .
 | 
			
		||||
            `, 400)
 | 
			
		||||
    } else {
 | 
			
		||||
        // Button A changes value, Button B selects value
 | 
			
		||||
        let ketone = getKetone()
 | 
			
		||||
        if (ketone != "HIGH") {
 | 
			
		||||
            // Button A changes value, Button B selects value
 | 
			
		||||
            let ill = getIll()
 | 
			
		||||
            if (!ill) {
 | 
			
		||||
                // Time to rest (jump into bed)
 | 
			
		||||
                basic.showAnimation(`
 | 
			
		||||
                    . . . . .   # # . . .   . # . . .   . # . . .   . . . # .   . . . . .
 | 
			
		||||
                    . . . . #   . . . . #   # # . . #   . # . . #   . . # . #   . . . . #
 | 
			
		||||
                    . . . . #   . . . . #   . . . . #   # # . . #   # # . . #   # # # # #
 | 
			
		||||
                    # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
                    # . . . #   # . . . #   # . . . #   # . . . #   # . . . #   # . . . #
 | 
			
		||||
                    `, 400)
 | 
			
		||||
            } else {
 | 
			
		||||
                // Test more often (clock shows 2 hour interval)
 | 
			
		||||
                basic.showAnimation(`
 | 
			
		||||
                    . . # . .   . . . . .   . . . . .   . . . . .   . # # . .   . . . . .   . # # . .   . . . . .   . # # . .
 | 
			
		||||
                    . . # . .   . . . . .   . . . . .   . . . . .   . . . # .   . . . . .   . . . # .   . . . . .   . . . # .
 | 
			
		||||
                    . . # . .   . . # # #   . . # . .   # # # . .   . . # . .   . . . . .   . . # . .   . . . . .   . . # . .
 | 
			
		||||
                    . . . . .   . . . . .   . . # . .   . . . . .   . # . . .   . . . . .   . # . . .   . . . . .   . # . . .
 | 
			
		||||
                    . . . . .   . . . . .   . . # . .   . . . . .   . # # # .   . . . . .   . # # # .   . . . . .   . # # # .
 | 
			
		||||
                    `, 400)
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // Get some help (call the diabetes care team on the phone)
 | 
			
		||||
            basic.showAnimation(`
 | 
			
		||||
                . . . . .   . . . . .   # # # # #   # # . . .   # # . . .   # # . . .   # # . . .   # # # . .   # # . # .   # # . . #
 | 
			
		||||
                . . . . .   # # # # #   # . . . #   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .
 | 
			
		||||
                # # # # #   # . . . #   . . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .
 | 
			
		||||
                # . # . #   . . # . .   . . # . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .   # . . . .
 | 
			
		||||
                . # # # .   . # # # .   . # # # .   # # . . .   # # . . #   # # . # .   # # # . .   # # . . .   # # . . .   # # . . .
 | 
			
		||||
                `, 400)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function waitAnyButton() {
 | 
			
		||||
    while (!input.buttonIsPressed(Button.A) && !input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,488 +0,0 @@
 | 
			
		||||
let AWasPressed: boolean
 | 
			
		||||
let BWasPressed: boolean
 | 
			
		||||
let wasShake: boolean
 | 
			
		||||
let dots025: Image
 | 
			
		||||
 | 
			
		||||
dots025 = images.createImage(`
 | 
			
		||||
    . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
    . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
    . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
    . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
    . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #
 | 
			
		||||
    `)
 | 
			
		||||
let tests = "DABPXYZSCT"
 | 
			
		||||
let test = 0
 | 
			
		||||
let prevTest = -1
 | 
			
		||||
startIOMonitor()
 | 
			
		||||
while (true) {
 | 
			
		||||
    let testLetter = tests[test]
 | 
			
		||||
    let autoRun = false
 | 
			
		||||
    if (testLetter == "D" || testLetter == "A" || testLetter == "B") {
 | 
			
		||||
        autoRun = true
 | 
			
		||||
    }
 | 
			
		||||
    if (!(test == prevTest)) {
 | 
			
		||||
        basic.showString(tests[test], 200)
 | 
			
		||||
        prevTest = test
 | 
			
		||||
    }
 | 
			
		||||
    if (AWasPressed || autoRun) {
 | 
			
		||||
        AWasPressed = false
 | 
			
		||||
        if (testLetter == "D") {
 | 
			
		||||
            testDisplay()
 | 
			
		||||
            test = test + 1
 | 
			
		||||
        } else if (testLetter == "A") {
 | 
			
		||||
            testButtonA()
 | 
			
		||||
            test = test + 1
 | 
			
		||||
        } else if (testLetter == "B") {
 | 
			
		||||
            testButtonB()
 | 
			
		||||
            test = test + 1
 | 
			
		||||
        } else if (testLetter == "P") {
 | 
			
		||||
            testPads()
 | 
			
		||||
        } else if (testLetter == "X") {
 | 
			
		||||
            testTiltX()
 | 
			
		||||
        } else if (testLetter == "Y") {
 | 
			
		||||
            testTiltY()
 | 
			
		||||
        } else if (testLetter == "Z") {
 | 
			
		||||
            testTiltZ()
 | 
			
		||||
        } else if (testLetter == "S") {
 | 
			
		||||
            testShake()
 | 
			
		||||
        } else if (testLetter == "C") {
 | 
			
		||||
            testCompass()
 | 
			
		||||
        } else if (testLetter == "T") {
 | 
			
		||||
            testTemperature()
 | 
			
		||||
        } else {
 | 
			
		||||
            // end of tests
 | 
			
		||||
            basic.showLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . #
 | 
			
		||||
                . . . # .
 | 
			
		||||
                # . # . .
 | 
			
		||||
                . # . . .
 | 
			
		||||
                `, 400)
 | 
			
		||||
        }
 | 
			
		||||
        prevTest = -1
 | 
			
		||||
        AWasPressed = false
 | 
			
		||||
        BWasPressed = false
 | 
			
		||||
    } else if (BWasPressed) {
 | 
			
		||||
        BWasPressed = false
 | 
			
		||||
        if (test < tests.length - 1) {
 | 
			
		||||
            test = test + 1
 | 
			
		||||
        } else {
 | 
			
		||||
            test = 3
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * flash all LEDs 5 times
 | 
			
		||||
 */
 | 
			
		||||
function testDisplay() {
 | 
			
		||||
    for (let i = 0; i < 5; i++) {
 | 
			
		||||
        basic.plotLeds(`
 | 
			
		||||
            # # # # #
 | 
			
		||||
            # # # # #
 | 
			
		||||
            # # # # #
 | 
			
		||||
            # # # # #
 | 
			
		||||
            # # # # #
 | 
			
		||||
            `)
 | 
			
		||||
        basic.pause(200)
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        basic.pause(200)
 | 
			
		||||
    }
 | 
			
		||||
    // cycle all LEDs from 1 to 25
 | 
			
		||||
    basic.showAnimation(`
 | 
			
		||||
        # . . . .   # # . . .   # # # . .   # # # # .   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #   # # # # #
 | 
			
		||||
        . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   . . . . .   # . . . .   # # . . .   # # # . .   # # # # .   # # # # #
 | 
			
		||||
        `, 400)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testButtonA() {
 | 
			
		||||
    basic.plotLeds(`
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . # # # .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        `)
 | 
			
		||||
    // wait for A pressed
 | 
			
		||||
    while (!input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
    basic.plotLeds(`
 | 
			
		||||
        . # . . .
 | 
			
		||||
        # . # . .
 | 
			
		||||
        # # # . .
 | 
			
		||||
        # . # . .
 | 
			
		||||
        # . # . .
 | 
			
		||||
        `)
 | 
			
		||||
    // wait for A released
 | 
			
		||||
    while (input.buttonIsPressed(Button.A)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
    basic.plotLeds(`
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . # # # .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        `)
 | 
			
		||||
    basic.pause(1000)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testTiltX() {
 | 
			
		||||
    basic.clearScreen()
 | 
			
		||||
    let prevx = 0
 | 
			
		||||
    while (!AWasPressed && !BWasPressed) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
        let x = input.acceleration(Dimension.X)
 | 
			
		||||
        let x2 = x / 512 + 2
 | 
			
		||||
        let x3 = Math.clamp(0, 4, x2)
 | 
			
		||||
        // sticky trace
 | 
			
		||||
        led.plot(x3, 0)
 | 
			
		||||
        // middle line is actual/live
 | 
			
		||||
        if (x3 != prevx) {
 | 
			
		||||
            led.unplot(prevx, 2)
 | 
			
		||||
            prevx = x3
 | 
			
		||||
        }
 | 
			
		||||
        led.plot(x3, 2)
 | 
			
		||||
        // bottom line is -4G, -2G, 1G, +2G, +4G
 | 
			
		||||
        if (x <= -2048) {
 | 
			
		||||
            led.plot(0, 4)
 | 
			
		||||
        } else if (x <= -1024) {
 | 
			
		||||
            led.plot(1, 4)
 | 
			
		||||
        } else if (x <= 1024) {
 | 
			
		||||
            led.plot(2, 4)
 | 
			
		||||
        } else if (x <= 2048) {
 | 
			
		||||
            led.plot(3, 4)
 | 
			
		||||
        } else {
 | 
			
		||||
            led.plot(4, 4)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testShake() {
 | 
			
		||||
    wasShake = false
 | 
			
		||||
    basic.plotLeds(`
 | 
			
		||||
        . . . . .
 | 
			
		||||
        . . . . .
 | 
			
		||||
        . . # . .
 | 
			
		||||
        . . . . .
 | 
			
		||||
        . . . . .
 | 
			
		||||
        `)
 | 
			
		||||
    while (!AWasPressed && !BWasPressed) {
 | 
			
		||||
        if (wasShake) {
 | 
			
		||||
            wasShake = false
 | 
			
		||||
            basic.plotLeds(`
 | 
			
		||||
                # # # # #
 | 
			
		||||
                # # # # #
 | 
			
		||||
                # # # # #
 | 
			
		||||
                # # # # #
 | 
			
		||||
                # # # # #
 | 
			
		||||
                `)
 | 
			
		||||
            basic.pause(500)
 | 
			
		||||
            basic.plotLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                `)
 | 
			
		||||
        } else {
 | 
			
		||||
            basic.pause(100)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testCompass() {
 | 
			
		||||
    if (input.compassHeading() < 0) {
 | 
			
		||||
        input.calibrate()
 | 
			
		||||
    }
 | 
			
		||||
    basic.clearScreen()
 | 
			
		||||
    while (!AWasPressed && !BWasPressed) {
 | 
			
		||||
        let d = input.compassHeading()
 | 
			
		||||
        d = d / 22
 | 
			
		||||
        d = Math.clamp(0, 15, d)
 | 
			
		||||
        d = (d + 2) % 16
 | 
			
		||||
        if (d < 4) {
 | 
			
		||||
            led.plot(d, 0)
 | 
			
		||||
        } else if (d < 8) {
 | 
			
		||||
            led.plot(4, d - 4)
 | 
			
		||||
        } else if (d < 12) {
 | 
			
		||||
            led.plot(4 - d - 8, 4)
 | 
			
		||||
        } else {
 | 
			
		||||
            led.plot(0, 4 - d - 12)
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testPads() {
 | 
			
		||||
    let TESTSPEED = 500
 | 
			
		||||
    AWasPressed = false
 | 
			
		||||
    BWasPressed = false
 | 
			
		||||
    // Make sure all pins are inputs, before test starts
 | 
			
		||||
    let p0 = pins.digitalReadPin(DigitalPin.P0)
 | 
			
		||||
    let p1 = pins.digitalReadPin(DigitalPin.P1)
 | 
			
		||||
    let p2 = pins.digitalReadPin(DigitalPin.P2)
 | 
			
		||||
    let ok0 = 0
 | 
			
		||||
    let ok1 = 0
 | 
			
		||||
    let ok2 = 0
 | 
			
		||||
    while (!AWasPressed && !BWasPressed) {
 | 
			
		||||
        basic.clearScreen()
 | 
			
		||||
        // ## P0 out low, read from P1 and P2
 | 
			
		||||
        ok0 = 0
 | 
			
		||||
        pins.digitalWritePin(DigitalPin.P0, 0)
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        p1 = pins.digitalReadPin(DigitalPin.P1)
 | 
			
		||||
        p2 = pins.digitalReadPin(DigitalPin.P2)
 | 
			
		||||
        if (p1 == 0) {
 | 
			
		||||
            led.plot(0, 0)
 | 
			
		||||
            ok0 = ok0 + 1
 | 
			
		||||
        }
 | 
			
		||||
        if (p2 == 0) {
 | 
			
		||||
            led.plot(1, 0)
 | 
			
		||||
            ok0 = ok0 + 1
 | 
			
		||||
        }
 | 
			
		||||
        // ## P0 out high, read from P1 and P2
 | 
			
		||||
        pins.digitalWritePin(DigitalPin.P0, 1)
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        p1 = pins.digitalReadPin(DigitalPin.P1)
 | 
			
		||||
        p2 = pins.digitalReadPin(DigitalPin.P2)
 | 
			
		||||
        if (p1 == 1) {
 | 
			
		||||
            led.plot(2, 0)
 | 
			
		||||
            ok0 = ok0 + 1
 | 
			
		||||
        }
 | 
			
		||||
        if (p2 == 1) {
 | 
			
		||||
            led.plot(3, 0)
 | 
			
		||||
            ok0 = ok0 + 1
 | 
			
		||||
        }
 | 
			
		||||
        // set back to an input
 | 
			
		||||
        p0 = pins.digitalReadPin(DigitalPin.P0)
 | 
			
		||||
        // ## P1 out low, read from P0 and P2
 | 
			
		||||
        ok1 = 0
 | 
			
		||||
        pins.digitalWritePin(DigitalPin.P1, 0)
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        p0 = pins.digitalReadPin(DigitalPin.P0)
 | 
			
		||||
        p2 = pins.digitalReadPin(DigitalPin.P2)
 | 
			
		||||
        if (p0 == 0) {
 | 
			
		||||
            led.plot(0, 1)
 | 
			
		||||
            ok1 = ok1 + 1
 | 
			
		||||
        }
 | 
			
		||||
        if (p2 == 0) {
 | 
			
		||||
            led.plot(1, 1)
 | 
			
		||||
            ok1 = ok1 + 1
 | 
			
		||||
        }
 | 
			
		||||
        // ## P1 out high, read from P0 and P2
 | 
			
		||||
        pins.digitalWritePin(DigitalPin.P1, 1)
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        p0 = pins.digitalReadPin(DigitalPin.P0)
 | 
			
		||||
        p2 = pins.digitalReadPin(DigitalPin.P2)
 | 
			
		||||
        if (p0 == 1) {
 | 
			
		||||
            led.plot(2, 1)
 | 
			
		||||
            ok1 = ok1 + 1
 | 
			
		||||
        }
 | 
			
		||||
        if (p2 == 1) {
 | 
			
		||||
            led.plot(3, 1)
 | 
			
		||||
            ok1 = ok1 + 1
 | 
			
		||||
        }
 | 
			
		||||
        // set back to an input
 | 
			
		||||
        p0 = pins.digitalReadPin(DigitalPin.P1)
 | 
			
		||||
        // ## P2 out low, read from P0 and P1
 | 
			
		||||
        ok2 = 0
 | 
			
		||||
        pins.digitalWritePin(DigitalPin.P2, 0)
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        p0 = pins.digitalReadPin(DigitalPin.P0)
 | 
			
		||||
        p1 = pins.digitalReadPin(DigitalPin.P1)
 | 
			
		||||
        if (p0 == 0) {
 | 
			
		||||
            led.plot(0, 2)
 | 
			
		||||
            ok2 = ok2 + 1
 | 
			
		||||
        }
 | 
			
		||||
        if (p1 == 0) {
 | 
			
		||||
            led.plot(1, 2)
 | 
			
		||||
            ok2 = ok2 + 1
 | 
			
		||||
        }
 | 
			
		||||
        // ## P2 out high, read from P0 and P1
 | 
			
		||||
        pins.digitalWritePin(DigitalPin.P2, 1)
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        p0 = pins.digitalReadPin(DigitalPin.P0)
 | 
			
		||||
        p1 = pins.digitalReadPin(DigitalPin.P1)
 | 
			
		||||
        if (p0 == 1) {
 | 
			
		||||
            led.plot(2, 2)
 | 
			
		||||
            ok2 = ok2 + 1
 | 
			
		||||
        }
 | 
			
		||||
        if (p1 == 1) {
 | 
			
		||||
            led.plot(3, 2)
 | 
			
		||||
            ok2 = ok2 + 1
 | 
			
		||||
        }
 | 
			
		||||
        p2 = pins.digitalReadPin(DigitalPin.P2)
 | 
			
		||||
        // ## Assess final test status
 | 
			
		||||
        if (ok0 == 4) {
 | 
			
		||||
            led.plot(4, 0)
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        if (ok1 == 4) {
 | 
			
		||||
            led.plot(4, 1)
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        if (ok2 == 4) {
 | 
			
		||||
            led.plot(4, 2)
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(TESTSPEED)
 | 
			
		||||
        if (ok0 + ok1 + ok2 == 12) {
 | 
			
		||||
            // all tests passed
 | 
			
		||||
            led.plot(4, 4)
 | 
			
		||||
        }
 | 
			
		||||
        // ## Test cycle finished
 | 
			
		||||
        basic.pause(1000)
 | 
			
		||||
    }
 | 
			
		||||
    // intentionally don't clear A and B flags, so main loop can process them.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * - show number of dots on screen (0..25) to represent temperature in celcius
 | 
			
		||||
 */
 | 
			
		||||
function testTemperature() {
 | 
			
		||||
    while (!AWasPressed && !BWasPressed) {
 | 
			
		||||
        let temp = input.temperature() - 10
 | 
			
		||||
        temp = Math.clamp(0, 25, temp)
 | 
			
		||||
        dots025.plotFrame(temp)
 | 
			
		||||
        basic.pause(500)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testButtonB() {
 | 
			
		||||
    basic.plotLeds(`
 | 
			
		||||
        . # # . .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . # # . .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . # # . .
 | 
			
		||||
        `)
 | 
			
		||||
    // wait for B pressed
 | 
			
		||||
    while (!input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
    basic.plotLeds(`
 | 
			
		||||
        . . # # .
 | 
			
		||||
        . . # . #
 | 
			
		||||
        . . # # .
 | 
			
		||||
        . . # . #
 | 
			
		||||
        . . # # .
 | 
			
		||||
        `)
 | 
			
		||||
    // wait for B released
 | 
			
		||||
    while (input.buttonIsPressed(Button.B)) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
    basic.plotLeds(`
 | 
			
		||||
        . # # . .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . # # . .
 | 
			
		||||
        . # . # .
 | 
			
		||||
        . # # . .
 | 
			
		||||
        `)
 | 
			
		||||
    basic.pause(1000)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testTiltY() {
 | 
			
		||||
    basic.clearScreen()
 | 
			
		||||
    let prevy = 0
 | 
			
		||||
    while (!AWasPressed && !BWasPressed) {
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
        let y = input.acceleration(Dimension.Y)
 | 
			
		||||
        let y2 = y / 512 + 2
 | 
			
		||||
        let y3 = Math.clamp(0, 4, y2)
 | 
			
		||||
        // sticky trace
 | 
			
		||||
        led.plot(0, y3)
 | 
			
		||||
        // middle line is actual/live
 | 
			
		||||
        if (y3 != prevy) {
 | 
			
		||||
            led.unplot(2, prevy)
 | 
			
		||||
            prevy = y3
 | 
			
		||||
        }
 | 
			
		||||
        led.plot(2, y3)
 | 
			
		||||
        // bottom line is -4G, -2G, 1G, +2G, +4G
 | 
			
		||||
        if (y <= -2048) {
 | 
			
		||||
            led.plot(4, 0)
 | 
			
		||||
        } else if (y <= -1024) {
 | 
			
		||||
            led.plot(4, 1)
 | 
			
		||||
        } else if (y <= 1024) {
 | 
			
		||||
            led.plot(4, 2)
 | 
			
		||||
        } else if (y <= 2048) {
 | 
			
		||||
            led.plot(4, 3)
 | 
			
		||||
        } else {
 | 
			
		||||
            led.plot(4, 4)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testTiltZ() {
 | 
			
		||||
    basic.clearScreen()
 | 
			
		||||
    while (!AWasPressed && !BWasPressed) {
 | 
			
		||||
        let z = input.acceleration(Dimension.Z)
 | 
			
		||||
        if (z < -2000) {
 | 
			
		||||
            basic.plotLeds(`
 | 
			
		||||
                # . . . #
 | 
			
		||||
                # . . . #
 | 
			
		||||
                # . . . #
 | 
			
		||||
                # . . . #
 | 
			
		||||
                # . . . #
 | 
			
		||||
                `)
 | 
			
		||||
        } else if (z <= -1030) {
 | 
			
		||||
            basic.plotLeds(`
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                . # . # .
 | 
			
		||||
                `)
 | 
			
		||||
        } else if (z <= 1000) {
 | 
			
		||||
            basic.plotLeds(`
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                . . # . .
 | 
			
		||||
                `)
 | 
			
		||||
        } else if (z <= 1030) {
 | 
			
		||||
            basic.plotLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                `)
 | 
			
		||||
        } else if (z <= 2000) {
 | 
			
		||||
            basic.plotLeds(`
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                . . . . .
 | 
			
		||||
                `)
 | 
			
		||||
        } else {
 | 
			
		||||
            basic.plotLeds(`
 | 
			
		||||
                # # # # #
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                . . . . .
 | 
			
		||||
                # # # # #
 | 
			
		||||
                `)
 | 
			
		||||
        }
 | 
			
		||||
        basic.pause(100)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function startIOMonitor() {
 | 
			
		||||
    input.onButtonPressed(Button.A, () => {
 | 
			
		||||
        AWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    input.onButtonPressed(Button.B, () => {
 | 
			
		||||
        BWasPressed = true
 | 
			
		||||
    })
 | 
			
		||||
    input.onShake(() => {
 | 
			
		||||
        wasShake = true
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user