Added a range of original TouchDevelop scripts converted to .ts for tests (#283)
This commit is contained in:
parent
8089fe262e
commit
2f11d603e7
222
tests/wg-canoe-polo-timer.ts
Normal file
222
tests/wg-canoe-polo-timer.ts
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
248
tests/wg-catching-raindrops.ts
Normal file
248
tests/wg-catching-raindrops.ts
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
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)
|
||||||
|
}
|
716
tests/wg-dr-who.ts
Normal file
716
tests/wg-dr-who.ts
Normal file
@ -0,0 +1,716 @@
|
|||||||
|
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() { }
|
165
tests/wg-flood-monitor.ts
Normal file
165
tests/wg-flood-monitor.ts
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
529
tests/wg-operation.ts
Normal file
529
tests/wg-operation.ts
Normal file
@ -0,0 +1,529 @@
|
|||||||
|
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()
|
||||||
|
}
|
178
tests/wg-operator-reaction-test.ts
Normal file
178
tests/wg-operator-reaction-test.ts
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
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)
|
||||||
|
}
|
157
tests/wg-paintroller.ts
Normal file
157
tests/wg-paintroller.ts
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
267
tests/wg-perfect-pancakes.ts
Normal file
267
tests/wg-perfect-pancakes.ts
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
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() { }
|
242
tests/wg-right-sugar.ts
Normal file
242
tests/wg-right-sugar.ts
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
488
tests/wg-user-confidance.ts
Normal file
488
tests/wg-user-confidance.ts
Normal file
@ -0,0 +1,488 @@
|
|||||||
|
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
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user