Add testBall.lua, testMain.lua, and testStatistics.lua
testMain.lua is really just a does-this-big-harness-work check right now, but it does work! Extract statistics.lua for testing Consolidate BoxScore ALL into draw/box-score.lua
This commit is contained in:
parent
48a9854653
commit
b44756ff57
|
@ -85,3 +85,8 @@ function Ball:launch(destX, destY, easingFunc, flyTimeMs, floaty, customBallScal
|
|||
self.floatAnimator:reset(flyTimeMs)
|
||||
end
|
||||
end
|
||||
|
||||
-- luacheck: ignore
|
||||
if not playdate or playdate.TEST_MODE then
|
||||
return Ball
|
||||
end
|
||||
|
|
|
@ -1,61 +1,3 @@
|
|||
---@alias TeamInningData { score: number, pitching: { balls: number, strikes: number }, hits: XyPair[] }
|
||||
|
||||
--- E.g. statistics[1].home.pitching.balls
|
||||
---@class Statistics
|
||||
---@field innings: (table<TeamId, TeamInningData>)[]
|
||||
|
||||
Statistics = {}
|
||||
|
||||
local function newTeamInning()
|
||||
return {
|
||||
score = 0,
|
||||
pitching = {
|
||||
balls = 0,
|
||||
strikes = 0,
|
||||
},
|
||||
hits = {},
|
||||
}
|
||||
end
|
||||
|
||||
---@return table<TeamId, TeamInningData>
|
||||
local function newInning()
|
||||
return {
|
||||
home = newTeamInning(),
|
||||
away = newTeamInning(),
|
||||
}
|
||||
end
|
||||
|
||||
---@return Statistics
|
||||
function Statistics.new()
|
||||
return setmetatable({
|
||||
innings = { newInning() },
|
||||
}, { __index = Statistics })
|
||||
end
|
||||
|
||||
function Statistics:pushInning()
|
||||
self.innings[#self.innings + 1] = newInning()
|
||||
end
|
||||
|
||||
---@class BoxScore
|
||||
---@field stats Statistics
|
||||
---@field private targetY number
|
||||
BoxScore = {}
|
||||
|
||||
---@param stats Statistics
|
||||
function BoxScore.new(stats)
|
||||
return setmetatable({
|
||||
stats = stats,
|
||||
targetY = 0,
|
||||
}, { __index = BoxScore })
|
||||
end
|
||||
|
||||
-- TODO? Some other stats
|
||||
-- * Scroll left and right through games that go into extra innings
|
||||
-- * Scroll up and down through other stats.
|
||||
-- + Balls and strikes
|
||||
-- + Batting average
|
||||
-- + Farthest hit ball
|
||||
|
||||
local MarginY <const> = 70
|
||||
|
||||
local SmallFont <const> = playdate.graphics.font.new("fonts/font-full-circle.pft")
|
||||
|
@ -101,6 +43,20 @@ local function drawInning(x, inningNumber, homeScore, awayScore)
|
|||
ScoreFont:drawTextAligned(homeScore, x, AwayY, gfx.kAlignRight)
|
||||
end
|
||||
|
||||
---@class BoxScore
|
||||
---@field stats Statistics
|
||||
---@field private targetY number
|
||||
BoxScore = {}
|
||||
|
||||
---@param stats Statistics
|
||||
---@return BoxScore
|
||||
function BoxScore.new(stats)
|
||||
return setmetatable({
|
||||
stats = stats,
|
||||
targetY = 0,
|
||||
}, { __index = BoxScore })
|
||||
end
|
||||
|
||||
function BoxScore:drawBoxScore()
|
||||
local inningStart = 4 + (AwayWidth * 1.5)
|
||||
local widthAndMarg = InningDrawWidth + 4
|
||||
|
|
13
src/main.lua
13
src/main.lua
|
@ -38,6 +38,7 @@ import 'fielding.lua'
|
|||
import 'graphics.lua'
|
||||
import 'npc.lua'
|
||||
import 'pitching.lua'
|
||||
import 'statistics.lua'
|
||||
|
||||
import 'draw/box-score.lua'
|
||||
import 'draw/fans.lua'
|
||||
|
@ -242,13 +243,10 @@ function Game:pitcherIsReady()
|
|||
end
|
||||
|
||||
function Game:checkForGameOver()
|
||||
local homeScore, awayScore = utils.totalScores(self.state.stats)
|
||||
local isFinalInning = self.state.inning >= self.settings.finalInning
|
||||
local gameOver = isFinalInning and self.state.battingTeam == "home" and awayScore ~= homeScore
|
||||
gameOver = gameOver or self.state.battingTeam == "away" and isFinalInning and homeScore > awayScore
|
||||
Fielding.celebrate()
|
||||
|
||||
if gameOver then
|
||||
local state = self.state
|
||||
if state.stats:gameIsOver(state.inning, self.settings.finalInning, state.battingTeam) then
|
||||
self.announcer:say("THAT'S THE BALL GAME!")
|
||||
playdate.timer.new(3000, function()
|
||||
transitionTo(BoxScore.new(self.state.stats))
|
||||
|
@ -727,6 +725,11 @@ function Game:update()
|
|||
end
|
||||
end
|
||||
|
||||
-- luacheck: ignore
|
||||
if not playdate or playdate.TEST_MODE then
|
||||
return Game
|
||||
end
|
||||
|
||||
playdate.display.setRefreshRate(50)
|
||||
gfx.setBackgroundColor(gfx.kColorWhite)
|
||||
playdate.setMenuImage(gfx.image.new("images/game/menu-image.png"))
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
-- TODO? Some other stats
|
||||
-- * Scroll left and right through games that go into extra innings
|
||||
-- * Scroll up and down through other stats.
|
||||
-- + Balls and strikes
|
||||
-- + Batting average
|
||||
-- + Farthest hit ball
|
||||
|
||||
local function newTeamInning()
|
||||
return {
|
||||
score = 0,
|
||||
pitching = {
|
||||
balls = 0,
|
||||
strikes = 0,
|
||||
},
|
||||
hits = {},
|
||||
}
|
||||
end
|
||||
|
||||
---@return table<TeamId, TeamInningData>
|
||||
local function newInning()
|
||||
return {
|
||||
home = newTeamInning(),
|
||||
away = newTeamInning(),
|
||||
}
|
||||
end
|
||||
|
||||
---@alias TeamInningData { score: number, pitching: { balls: number, strikes: number }, hits: XyPair[] }
|
||||
|
||||
--- E.g. statistics[1].home.pitching.balls
|
||||
---@class Statistics
|
||||
---@field innings (table<TeamId, TeamInningData>)[]
|
||||
Statistics = {}
|
||||
|
||||
---@return Statistics
|
||||
function Statistics.new()
|
||||
return setmetatable({
|
||||
innings = { newInning() },
|
||||
}, { __index = Statistics })
|
||||
end
|
||||
|
||||
function Statistics:pushInning()
|
||||
self.innings[#self.innings + 1] = newInning()
|
||||
end
|
||||
|
||||
---@param inning number
|
||||
---@param finalInning number
|
||||
---@param battingTeam TeamId
|
||||
---@return boolean gameOver
|
||||
function Statistics:gameIsOver(inning, finalInning, battingTeam)
|
||||
local homeScore, awayScore = utils.totalScores(self)
|
||||
local isFinalInning = inning >= finalInning
|
||||
local gameOver = isFinalInning and battingTeam == "home" and awayScore ~= homeScore
|
||||
gameOver = gameOver or battingTeam == "away" and isFinalInning and homeScore > awayScore
|
||||
return gameOver
|
||||
end
|
||||
|
||||
-- luacheck: ignore
|
||||
if not playdate or playdate.TEST_MODE then
|
||||
return Statistics
|
||||
end
|
|
@ -2,7 +2,9 @@ utils = require("utils")
|
|||
|
||||
local currentTimeMs = 0
|
||||
|
||||
local mockPlaydate = {
|
||||
local mockPlaydate = {}
|
||||
|
||||
mockPlaydate = {
|
||||
TEST_MODE = true,
|
||||
skipMs = function(skip)
|
||||
currentTimeMs = currentTimeMs + skip
|
||||
|
@ -11,13 +13,21 @@ local mockPlaydate = {
|
|||
currentTimeMs = currentTimeMs + 1
|
||||
return currentTimeMs
|
||||
end,
|
||||
easingFunctions = {},
|
||||
timer = {
|
||||
lastTimer = {
|
||||
mockCompletion = function()
|
||||
error("No lastTimer set!")
|
||||
end,
|
||||
},
|
||||
new = function(_, callback)
|
||||
return {
|
||||
local timer = {
|
||||
mockCompletion = function()
|
||||
callback()
|
||||
end,
|
||||
}
|
||||
mockPlaydate.timer.lastTimer = timer
|
||||
return timer
|
||||
end,
|
||||
},
|
||||
graphics = {
|
||||
|
@ -38,6 +48,21 @@ local mockPlaydate = {
|
|||
return {}
|
||||
end,
|
||||
},
|
||||
image = {
|
||||
new = function()
|
||||
return {}
|
||||
end,
|
||||
},
|
||||
},
|
||||
sound = {
|
||||
sampleplayer = {
|
||||
new = function()
|
||||
return {
|
||||
play = function() end,
|
||||
setFinishCallback = function() end,
|
||||
}
|
||||
end,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
require("test/setup")
|
||||
|
||||
local Ball = require("ball")
|
||||
|
||||
function testMarkUncatchable()
|
||||
local ball = Ball.new(playdate.graphics.animator)
|
||||
luaunit.assertIsTrue(ball.catchable, "Ball should start catchable")
|
||||
ball:markUncatchable()
|
||||
luaunit.assertIsFalse(ball.catchable, "Ball should not be catchable immediately after mark")
|
||||
playdate.timer.lastTimer.mockCompletion()
|
||||
luaunit.assertIsTrue(ball.catchable, "Ball should return to catchability after its timer expires")
|
||||
end
|
||||
|
||||
os.exit(luaunit.LuaUnit.run())
|
|
@ -0,0 +1,28 @@
|
|||
require("test/setup")
|
||||
require("draw/panner")
|
||||
|
||||
function string.starts(str, start)
|
||||
return string.sub(str, 1, str.len(start)) == start
|
||||
end
|
||||
|
||||
import = function(target)
|
||||
if string.starts(target, "CoreLibs") or string.starts(target, "draw/") then
|
||||
return
|
||||
end
|
||||
-- Remove .lua
|
||||
require(target:sub(1, #target - 4))
|
||||
end
|
||||
|
||||
local Game = require("main")
|
||||
|
||||
local settings = {
|
||||
homeTeamSpriteGroup = {},
|
||||
awayTeamSpriteGroup = {},
|
||||
}
|
||||
|
||||
function testStandaloneInit()
|
||||
-- Harness should be fleshed-out enough to init without error.
|
||||
Game.new(settings, announcer)
|
||||
end
|
||||
|
||||
os.exit(luaunit.LuaUnit.run())
|
|
@ -0,0 +1,19 @@
|
|||
require("test/setup")
|
||||
|
||||
local Statistics = require("statistics")
|
||||
|
||||
function testReportGameOver()
|
||||
---@type Statistics
|
||||
local stats = Statistics.new()
|
||||
stats.innings[1].home.score = 0
|
||||
stats.innings[1].away.score = 0
|
||||
luaunit.assertIsFalse(stats:gameIsOver(9, 9, "home"), "Tie games should not report a game over")
|
||||
|
||||
stats.innings[1].home.score = 1
|
||||
luaunit.assertIsTrue(stats:gameIsOver(9, 9, "home"), "Team in lead should report a game over")
|
||||
|
||||
stats.innings[1].home.score = 1
|
||||
luaunit.assertIsFalse(stats:gameIsOver(1, 9, "home"), "Should not game over with innings left")
|
||||
end
|
||||
|
||||
os.exit(luaunit.LuaUnit.run())
|
Loading…
Reference in New Issue