Skip to content

Instantly share code, notes, and snippets.

@bcatcho
Created October 16, 2012 03:05
Show Gist options
  • Save bcatcho/3897045 to your computer and use it in GitHub Desktop.
Save bcatcho/3897045 to your computer and use it in GitHub Desktop.
Added a new debug method and a namespace for all debug methods "dbg"
--# Debug
dbg = {}
setmetatable(dbg, { __index = dbg })
dbg.traceback = function()
local level = 1
while true do
local info = debug.getinfo(level, "Sl")
if not info then break end
if info.what == "C" then -- is a C function?
print(level, "C function")
else -- a Lua function
print(string.format("[%s]:%d", info.short_src, info.currentline))
end
level = level + 1
end
end
dbg.timeFunc = function (func, ...)
local t = os.clock()
local result = func(unpack(arg))
return result, os.clock() - t
end
--# ObserverTable
ObserverTable = class()
function ObserverTable:init()
-- you can accept and set parameters here
self.t = {}
end
function ObserverTable:observe(key, topic, delegagte)
if self.t[key] == nil then
self.t[key] = {}
end
if self.t[key][topic] == nil then
self.t[key][topic] = {}
end
table.insert(self.t[key][topic], delegate)
end
function ObserverTable:notify(key, topic, ...)
if self.t[key] ~= nil then
if self.t[key][topic] ~= nil then
for key, d in ipairs(self.t[key][topic]) do
d(unpack(arg))
end
end
end
end
--# State
State = class()
function State:init(...)
self.sm = nil
self:initState(unpack(arg))
end
function State:setStateMachine(stateMachine)
self.sm = stateMachine
end
function State:goState(state)
self.sm:transitionTo(state)
end
function State:shared()
return self.sm:getSharedProps()
end
-- virtual
function State:initState()
end
-- virtual
function State:enter()
end
-- virtual
function State:exit()
end
--# StateMachine
StateMachine = class()
function StateMachine:init()
self.state = nil
self._sharedProps = {}
end
function StateMachine:startWith(initialState)
self.state = initialState
self.state:setStateMachine(self)
self.state:enter()
end
-- properties that will be passed from state to state
function StateMachine:setSharedProperties(props)
for k,v in pairs(props) do
self._sharedProps[k] = v
end
end
function StateMachine:getSharedProps()
return self._sharedProps
end
function StateMachine:transitionTo(nextState)
self.state:exit()
self.state = nextState
self.state:setStateMachine(self)
self.state:enter()
end
function StateMachine:current()
return self.state
end
--# TableExtensions
function T(t)
return setmetatable(t, {__index = table})
end
table.reduce = function(tbl, seed, func )
local sum = seed
for k,v in pairs(tbl) do
sum = func(v, sum)
end
return sum
end
table.doXY = function(cols, rows, func)
for r = 1, rows do
for c = 1, cols do
func(c, r)
end
end
end
table.map = function(tbl, func)
local result = T{}
for k, v in pairs(tbl) do
result:insert(func(v, k) )
end
return result
end
table.each = function(tbl, func)
for k, v in pairs(tbl) do
func(v, k)
end
end
table.eachIf = function(tbl, filter, func)
local result = T{}
for k, v in pairs(tbl) do
if filter(v,k) then
result[k] = func(v,k)
end
end
return result
end
table.eachIfA = function(tbl, filter, func)
local result = T{}
for k, v in pairs(tbl) do
if filter(v,k) then
result:insert(func(v,k))
end
end
return result
end
table.filter = function(tbl, func)
local result = T{}
for k, v in pairs(tbl) do
if func(v,k) then
result[k] = v
end
end
return result
end
table.filterA = function(tbl, func)
local result = T{}
for k, v in ipairs(tbl) do
if func(v,k) then
result[#result+1] = v
end
end
return result
end
table.mapSet = function(tbl, func)
local result = T{}
local track = {} -- keep track of the values we have seen
local ouput -- optimization
for k, v in pairs(tbl) do
output = func(v, k)
if track[output] == nil then
result:insert(output)
track[output] = true
end
end
return result
end
--# TGrid
TGrid = class(ObserverTable)
function TGrid:init(w, h)
ObserverTable.init(self)
-- you can accept and set parameters here
self.w = w
self.h = h
self.grid = {}
self.gridByY = {}
end
-- iterator by Y value from top of screen to bottom
function TGrid:listTtoB()
local w, h = self.w, self.h
local fn = function(state, loopvar)
if state.y > 0 then
state.x = state.x+1
if state.x > w then
state.x = 1
state.y = state.y - 1
end
return self:get(state.x, state.y)
end
return nil
end
return fn, {x = 0, y = h}, 0
end
function TGrid:listBtoT()
local w, h = self.w, self.h
local fn = function(state, loopvar)
if state.y <= h then
state.x = state.x+1
if state.x > w then
state.x = 1
state.y = state.y + 1
end
return self:get(state.x, state.y)
end
return nil
end
return fn, {x = 0, y = 1}, 0
end
function TGrid:gIndex(x,y)
return x..','..y
end
function TGrid:add(x, y, value)
self.grid[self:gIndex(x,y)] = value
--table.insert(self.gridByY, (y-1), self:get(x,y))
end
function TGrid:get(x,y)
return self.grid[self:gIndex(x,y)]
end
function TGrid:getN(x,y)
return self:get(x,y-1)
end
function TGrid:getE(x,y)
return self:get(x+1,y)
end
function TGrid:getS(x,y)
return self:get(x,y+1)
end
function TGrid:getW(x,y)
return self:get(x-1,y)
end
function TGrid:set(x,y, value)
self.grid[self:gIndex(x,y)] = value
end
function TGrid:setk(x,y, key, value)
self.grid[self:gIndex(x,y)][key] = value
end
function TGrid:getAround(x,y)
return {
self:getN(x,y),
self:getE(x,y),
self:getS(x,y),
self:getW(x,y)
}
end
--# Util
-- String.format
_fmt = function(...)
return string.format(unpack(arg))
end
--# Main
-- Common
-- this project is just a container for common classes and utilities
local output = ""
local pass, fail = 0, 0
function test(name, t)
local outputFunc = function(...)
print(" "..string.format(unpack(arg)))
end
local expected, actual = t(outputFunc)
if expected == actual then
output = output.."."
pass = pass + 1
else
print(output)
output = ""
print("!! "..name)
print(" "..tostring(expected).."\n "..tostring(actual).."\n")
fail = fail + 1
end
end
function setup()
test( "table.reduce",
function ()
t = {2, 3}
local result = table.reduce(t, 1, function(a, rest) return a*rest end)
return 6, result
end)
test( "table.doXY",
function ()
local total = 0
table.doXY(2,2, function(x,y) total = total + x + y end)
return 12, total
end)
test("table.map",
function ()
local map = table.map({"yar","word","to"}, string.len)
return 4, map[2]
end)
test("table.mapSet",
function ()
local map = table.mapSet({"yar","yar","to"}, string.format)
return "to", map[2]
end)
test("table.eachIf",
function ()
local t = T{1,3,"adf"}
local result = t:eachIf(function (v) return type(v) == "string" end, string.upper )
return "ADF", result[3]
end)
test("table.eachIfA",
function ()
local t = T{1,3,"adf"}
local result = t:eachIfA(function (v) return type(v) == "string" end, string.upper )
return "ADF", result[1]
end)
test("table.filterA",
function ()
local filteredList = table.filterA({1,2,3}, function (v,k) return v > 2 end)
return 3, filteredList[1]
end)
test("table.filter",
function ()
local filteredList = table.filter({a=1,b=2,c=3}, function (v,k) return v > 2 end)
return 3, filteredList.c
end)
test("T()",
function ()
local tbl = T{}
tbl:insert(1.5)
tbl = tbl:map(math.floor)
return 1, tbl[1]
end)
test("_fmt",
function ()
local result = _fmt("%d,%i,%f", 123.0, 123.0, 123.0)
return "123,123,123.000000", result
end)
test("dbg.timeFunc",
function ()
local function f (a)
local sum = 0
for i=1, a do sum = sum + 1 end
return sum
end
local result, time = dbg.timeFunc(f, 100000)
return "100000,true", result..","..tostring(time < 1 and time > 0)
end)
print(output)
print((fail == 0) and "All tests passed" or _fmt("%d/%d tests passed",pass,pass+fail))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment