├── .gitignore ├── MoacatTestCases ├── README.md ├── fonts │ └── arial-rounded.TTF ├── images │ ├── camera.png │ ├── cathead.png │ ├── moai-attribution-black-256.png │ └── numbers.png ├── test_moai_environment.lua ├── test_moai_event.lua ├── test_moai_event_recorder.lua ├── test_moai_file_system.lua ├── test_moai_image.lua ├── test_moai_label.lua ├── test_moai_parallax.lua ├── test_moai_pen.lua ├── test_moai_prop_parent.lua ├── test_moai_properties.lua ├── test_moai_sprite.lua ├── test_moai_textbox.lua └── test_moai_tile.lua ├── Quiz ├── README.md ├── test_draw_shapes.lua ├── test_hexagon_walk.lua ├── test_indexes_to_ranges.lua ├── test_obfuscation.lua └── test_parse_url.lua ├── README.md ├── TestCases ├── test_all.lua ├── test_casestatement.lua ├── test_coroutine.lua ├── test_dateext.lua ├── test_exception.lua ├── test_file.lua ├── test_hangul.lua ├── test_logger.lua ├── test_luacat.lua ├── test_metatable.lua ├── test_numberext.lua ├── test_objectext.lua ├── test_setup_teardown.lua ├── test_stringext.lua ├── test_tableext.lua └── test_unittest.lua ├── luacat ├── CaseStatement.lua ├── DateExt.lua ├── Exception.lua ├── File.lua ├── Hangul.lua ├── Logger.lua ├── NumberExt.lua ├── ObjectExt.lua ├── StringExt.lua ├── TableExt.lua ├── UnitTest.lua ├── inspect.lua └── luacat.lua └── moacat ├── Anim.lua ├── Button.lua ├── Color.lua ├── Debug.lua ├── Deck.lua ├── Device.lua ├── Environment.lua ├── Event.lua ├── EventRecorder.lua ├── Font.lua ├── Geometry.lua ├── Grid.lua ├── Image.lua ├── Label.lua ├── Layer.lua ├── MoaiInfo.lua ├── MoaiNode.lua ├── PackagePath.lua ├── Pen.lua ├── Prop.lua ├── Screen.lua ├── ScriptDeck.lua ├── Sim.lua ├── Sprite.lua ├── System.lua ├── TextButton.lua ├── Transform.lua ├── Viewport.lua └── moacat.lua /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /MoacatTestCases/README.md: -------------------------------------------------------------------------------- 1 | 2 | $ moai test_moai_image.lua 3 | Started 4 | ... 5 | Finished in 0.0330 seconds. 6 | 1 tests, 3 assertions, 0 failures, 0 errors 7 | exit 8 | -------------------------------------------------------------------------------- /MoacatTestCases/fonts/arial-rounded.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wookay/luacat/ecef193ba1ef9b7bfdee78bf85a4a9833885e7b6/MoacatTestCases/fonts/arial-rounded.TTF -------------------------------------------------------------------------------- /MoacatTestCases/images/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wookay/luacat/ecef193ba1ef9b7bfdee78bf85a4a9833885e7b6/MoacatTestCases/images/camera.png -------------------------------------------------------------------------------- /MoacatTestCases/images/cathead.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wookay/luacat/ecef193ba1ef9b7bfdee78bf85a4a9833885e7b6/MoacatTestCases/images/cathead.png -------------------------------------------------------------------------------- /MoacatTestCases/images/moai-attribution-black-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wookay/luacat/ecef193ba1ef9b7bfdee78bf85a4a9833885e7b6/MoacatTestCases/images/moai-attribution-black-256.png -------------------------------------------------------------------------------- /MoacatTestCases/images/numbers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wookay/luacat/ecef193ba1ef9b7bfdee78bf85a4a9833885e7b6/MoacatTestCases/images/numbers.png -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_environment.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_environment.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_environment() 8 | assert_equal({ AppDisplayName = "UNKNOWN", 9 | AppID = "UNKNOWN", 10 | AppVersion = "UNKNOWN", 11 | CPUABI = "UNKNOWN", 12 | CacheDirectory = "UNKNOWN", 13 | CarrierISOCountryCode = "UNKNOWN", 14 | CarrierMobileCountryCode = "UNKNOWN", 15 | CarrierMobileNetworkCode = "UNKNOWN", 16 | CarrierName = "UNKNOWN", 17 | ConnectionType = 0, 18 | CountryCode = "UNKNOWN", 19 | DevBrand = "UNKNOWN", 20 | DevManufacturer = "UNKNOWN", 21 | DevModel = "UNKNOWN", 22 | DevName = "UNKNOWN", 23 | DevProduct = "UNKNOWN", 24 | DocumentDirectory = "UNKNOWN", 25 | LanguageCode = "UNKNOWN", 26 | OSBrand = 2, 27 | OSVersion = "UNKNOWN", 28 | ResourceDirectory = "UNKNOWN", 29 | UDID = "UNKNOWN", 30 | ViewSize = 0, 31 | isRetinaDisplay = false}, Environment) 32 | end 33 | 34 | 35 | 36 | if is_main() then 37 | UnitTest.run() 38 | end 39 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_event.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_event.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_event() 8 | local layer = Sim.layer() 9 | layer.enableTouchEvents() 10 | 11 | local deck = Deck.new("./images/cathead.png") 12 | local prop = Prop.new(deck) 13 | prop.origin = {0,0} 14 | prop.addListener(Prop.drag_listener) 15 | prop.addListener(Prop.ended_listener, function(event) 16 | moai_info('event', event.phase, event.location) 17 | end) 18 | layer.add(prop) 19 | 20 | local prop = Prop.new(deck) 21 | prop.origin = {0,Screen.height - deck.image.height} 22 | prop.addListener(Prop.drag_listener) 23 | prop.addListener(Prop.ended_listener, function() 24 | moai_info('prop', prop.wrap) 25 | end) 26 | layer.add(prop) 27 | 28 | layer.addExitButton() 29 | end 30 | 31 | 32 | if is_main() then 33 | UnitTest.run() 34 | end 35 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_event_recorder.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_event_recorder.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | require 'EventRecorder' 7 | 8 | function test_moai_event_recorder() 9 | local layer = Sim.layer() 10 | layer.enableTouchEvents() 11 | 12 | function layer.addButton(title, origin, fun) 13 | local button = TextButton.new(title, fun) 14 | button.frame = {origin, {100,40}} 15 | layer.add(button) 16 | end 17 | 18 | local recorder = EventRecorder.new() 19 | layer.addButton("Start", {210,125}, function() 20 | recorder.start() 21 | moai_info('start') 22 | end) 23 | layer.addButton("Stop", {210,175}, function() 24 | recorder.stop() 25 | moai_info('stop') 26 | end) 27 | layer.addButton("Replay", {210,225}, function() 28 | recorder.replay() 29 | moai_info('replay') 30 | end) 31 | layer.addButton("Save", {210,275}, function() 32 | recorder.save() 33 | moai_info('save') 34 | end) 35 | layer.addButton("Load", {210,325}, function() 36 | recorder.load() 37 | moai_info('load') 38 | end) 39 | 40 | layer.addExitButton() 41 | end 42 | 43 | 44 | if is_main() then 45 | UnitTest.run() 46 | end 47 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_file_system.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_file_system.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_file_system() 8 | 9 | assert_true( 10 | String.end_with(MOAIFileSystem:getAbsoluteFilePath(), 11 | 'MoacatTestCases/')) 12 | assert_true( 13 | String.end_with(MOAIFileSystem:getAbsoluteDirectoryPath(), 14 | 'MoacatTestCases/')) 15 | assert_true( 16 | String.end_with(MOAIFileSystem:getWorkingDirectory(), 17 | 'MoacatTestCases/')) 18 | 19 | assert_equal({".", "..", "fonts", "images"}, 20 | MOAIFileSystem:listDirectories()) 21 | 22 | assert_true( 23 | Table.include(MOAIFileSystem:listFiles(), 24 | 'test_moai_file_system.lua')) 25 | 26 | --[[ 27 | MOAIFileSystem 28 | affirmPath -- Creates a folder at 'path' if none exists. 29 | checkFileExists -- Check for the existence of a file. 30 | checkPathExists -- Check for the existence of a path. 31 | deleteDirectory -- Deletes a directory and all of its contents. 32 | deleteFile -- Deletes a file 33 | getAbsoluteFilePath -- Returns the absolute path to a file. Result includes the file name. 34 | getAbsoluteDirectoryPath -- Returns the absolute path given a relative path. 35 | getWorkingDirectory -- Returns the path to current working directory. 36 | listDirectories -- Lists the sub-directories contained in a directory. 37 | listFiles -- Lists the files contained in a directory. 38 | mountVirtualDirectory -- Mount an archive as a virtual filesystem directory. 39 | rename -- Renames a file or folder. 40 | setWorkingDirectory -- Sets the current working directory. 41 | ]]-- 42 | end 43 | 44 | 45 | 46 | if is_main() then 47 | UnitTest.run() 48 | end 49 | 50 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_image.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_image.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | package.path = package.path .. ";../moacat/?.lua" 6 | require 'moacat' 7 | 8 | function test_moai_image() 9 | local layer = Sim.layer() 10 | 11 | local deck = Deck.new("./images/cathead.png") 12 | 13 | local prop = Prop.new(deck) 14 | prop.origin = {0,0} 15 | layer.add(prop) 16 | 17 | local prop = Prop.new(deck) 18 | prop.origin = {Screen.width - deck.image.width,0} 19 | layer.add(prop) 20 | 21 | assert_equal({Screen.width - deck.image.width,0}, prop.origin) 22 | 23 | local prop = Prop.new(deck) 24 | prop.origin = {0,Screen.height - deck.image.height} 25 | layer.add(prop) 26 | 27 | local prop = Prop.new(deck) 28 | prop.origin = {Screen.width - deck.image.width, 29 | Screen.height - deck.image.height} 30 | layer.add(prop) 31 | 32 | local prop = Prop.new(deck) 33 | prop.origin = {Screen.halfWidth - deck.image.width/2, 34 | Screen.halfHeight - deck.image.height/2} 35 | layer.add(prop) 36 | 37 | assert_equal('MOAILayer2D', layer.wrap:getClassName()) 38 | assert_equal(0, layer.wrap:getLoc()) 39 | 40 | System.exit_after_seconds(0.5) 41 | end 42 | 43 | 44 | if is_main() then 45 | UnitTest.run() 46 | end 47 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_label.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_label.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_label() 8 | local layer = Sim.layer() 9 | 10 | local label = Label.new("hello") 11 | label.frame = {{0,0}, {100,50}} 12 | layer.add(label) 13 | 14 | label.text = "hello2" 15 | assert_equal("hello2", label.text) 16 | 17 | assert_equal({{0,0}, {100,50}}, label.frame) 18 | 19 | label.frame = {{100,10}, {100,50}} 20 | assert_equal({{100,10}, {100,50}}, label.frame) 21 | 22 | System.exit_after_seconds(0.5) 23 | end 24 | 25 | 26 | if is_main() then 27 | UnitTest.run() 28 | end 29 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_parallax.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_parallax.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | package.path = package.path .. ";../moacat/?.lua" 6 | require 'moacat' 7 | 8 | function test_moai_parallax() 9 | System.openWindow() 10 | 11 | local viewport = Viewport.new() 12 | 13 | local backLayer = Layer.new(viewport) 14 | backLayer.parallax = {0.1, 0.1} 15 | Sim.push(backLayer) 16 | 17 | 18 | local frontLayer = Layer.new(viewport) 19 | frontLayer.enableTouchEvents() 20 | Sim.push(frontLayer) 21 | 22 | local deck = Deck.new("./images/moai-attribution-black-256.png") 23 | local prop = Prop.new(deck) 24 | backLayer.add(prop) 25 | 26 | local camera = Transform.new() 27 | backLayer.camera = camera 28 | local cameraDeck = Deck.new("./images/camera.png") 29 | local cameraProp = Prop.new(cameraDeck) 30 | cameraProp.origin = {Screen.width - 150, Screen.height - 150} 31 | cameraProp.addListener(function(event) 32 | local offset = Location.diff(event.location, event.previousLocation) 33 | local loc = Location.multiplyOffset(camera.location, offset, -2) 34 | camera.seekLocation(loc) 35 | end) 36 | 37 | local catDeck = Deck.new("./images/cathead.png") 38 | local catProp = Prop.new(catDeck) 39 | catProp.origin = {50,150} 40 | catProp.addListener(Prop.drag_listener) 41 | frontLayer.add(catProp) 42 | frontLayer.add(cameraProp) 43 | 44 | frontLayer.addExitButton() 45 | end 46 | 47 | 48 | if is_main() then 49 | UnitTest.run() 50 | end 51 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_pen.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_pen.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_pen() 8 | local layer = Sim.layer() 9 | 10 | local pen = Pen.new(layer) 11 | pen.width = 3 12 | pen.drawRect({{5,5},{100,150}}) 13 | 14 | local pen = Pen.new(layer) 15 | pen.color = Color.green 16 | pen.fillRect({{Screen.width-105,5},{100,150}}) 17 | 18 | System.exit_after_seconds(0.5) 19 | end 20 | 21 | 22 | 23 | if is_main() then 24 | UnitTest.run() 25 | end 26 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_prop_parent.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_prop_parent.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | package.path = package.path .. ";../moacat/?.lua" 6 | require 'moacat' 7 | 8 | function test_moai_prop_parent() 9 | local layer = Sim.layer() 10 | layer.enableTouchEvents() 11 | 12 | local catDeck = Deck.new("./images/cathead.png") 13 | assert_equal({128,128}, catDeck.size) 14 | local catProp = Prop.new(catDeck) 15 | catProp.origin = {0,0} 16 | 17 | local deck = Deck.new("./images/moai-attribution-black-256.png") 18 | assert_equal({256,256}, deck.size) 19 | local prop = Prop.new(deck) 20 | prop.origin = {100,256+64} 21 | prop.parent = catProp 22 | layer.add(prop) 23 | layer.add(catProp) 24 | 25 | local loc_fun = function(e) 26 | if Phase.ended == e.phase then 27 | --moai_info('Origin: ', catProp.origin, prop.origin) 28 | moai_info('Loc: ', catProp.location, prop.location) 29 | end 30 | end 31 | 32 | catProp.addListener(Prop.drag_listener, loc_fun) 33 | prop.addListener(Prop.drag_listener, loc_fun) 34 | 35 | layer.addExitButton() 36 | end 37 | 38 | 39 | if is_main() then 40 | UnitTest.run() 41 | end 42 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_properties.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_properties.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_properties() 8 | local viewport = MOAIViewport.new() 9 | -- moai_info('viewport', viewport) 10 | 11 | local layer = MOAILayer2D.new() 12 | -- moai_info('layer', layer) 13 | --[[ 14 | 15 | Grid nil 16 | Index 1 17 | Loc 0 18 | Partition nil 19 | Priority nil 20 | Rot 0 21 | Scl 1 22 | WorldDir 1 23 | WorldLoc 0 24 | WorldRot 90 25 | WorldScl 1 26 | ]]-- 27 | 28 | layer:setViewport(viewport) 29 | MOAISim.pushRenderPass(layer) 30 | 31 | local deck = MOAIGfxQuad2D.new() 32 | --moai_info('deck', deck) 33 | 34 | local prop = MOAIProp2D.new () 35 | -- moai_info('prop', prop) 36 | --[[ 37 | 38 | Grid nil 39 | Index 1 40 | Loc 0 41 | Priority nil 42 | Rot 0 43 | Scl 1 44 | WorldDir 1 45 | WorldLoc 0 46 | WorldRot 90 47 | WorldScl 1 48 | ]]-- 49 | 50 | prop:setDeck(deck) 51 | layer:insertProp(prop) 52 | --moai_info('prop', prop) 53 | --moai_info('layer', layer) 54 | --[[ 55 | 56 | Grid nil 57 | Index 1 58 | Loc 0 59 | Partition 0x0xa6f46c 60 | Priority nil 61 | Rot 0 62 | Scl 1 63 | WorldDir 1 64 | WorldLoc 0 65 | WorldRot 90 66 | WorldScl 1 67 | ]]-- 68 | 69 | assert_equal('MOAILayer2D', layer:getClassName()) 70 | assert_equal(0, layer:getLoc()) 71 | 72 | -- methods 73 | --log_info('layer', layer.__index) 74 | --log_info('layer', layer.__newindex) 75 | end 76 | 77 | 78 | if is_main() then 79 | UnitTest.run() 80 | end 81 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_sprite.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_sprite.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_sprite() 8 | local layer = Sim.layer() 9 | layer.enableTouchEvents() 10 | 11 | local deck = Deck.new("./images/numbers.png", {8,8}) 12 | 13 | local prop = Prop.new(deck) 14 | prop.origin = {10,10} 15 | layer.add(prop) 16 | prop.addListener(Prop.drag_listener) 17 | local sprite = Sprite.new(prop, { interval = 0.1 }) 18 | sprite.play() 19 | --sprite.pause() 20 | 21 | local prop = Prop.new(deck) 22 | prop.origin = {150,10} 23 | layer.add(prop) 24 | prop.addListener(Prop.drag_listener) 25 | local sprite = Sprite.new(prop, { interval = 0.2 }) 26 | sprite.play() 27 | 28 | layer.addExitButton() 29 | end 30 | 31 | 32 | if is_main() then 33 | UnitTest.run() 34 | end 35 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_textbox.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_textbox.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_textbox() 8 | local layer = Sim.layer() 9 | 10 | local text = "hello\nworld" 11 | local mtextbox = MOAITextBox.new() 12 | mtextbox:setString(text) 13 | local font = Font.new() 14 | mtextbox:setFont(font.wrap) 15 | local textSize = font.wrap:getScale() 16 | mtextbox:setTextSize(textSize) 17 | mtextbox:setYFlip(true) 18 | mtextbox:setRect(0, 0, 100, font.wrap:getLineScale()*2) 19 | --log_info('getLineSize', mtextbox:getLineSize()) 20 | --log_info('getStringBounds', mtextbox:getStringBounds(1, #text)) 21 | layer.wrap:insertProp(mtextbox) 22 | 23 | System.exit_after_seconds(0.5) 24 | end 25 | 26 | 27 | if is_main() then 28 | UnitTest.run() 29 | end 30 | -------------------------------------------------------------------------------- /MoacatTestCases/test_moai_tile.lua: -------------------------------------------------------------------------------- 1 | -- test_moai_tile.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../moacat/?.lua" 5 | require 'moacat' 6 | 7 | function test_moai_tile() 8 | local layer = Sim.layer() 9 | 10 | local deck = Deck.new("./images/numbers.png", {8,8}) 11 | assert_equal({32,32}, deck.size) 12 | 13 | local deckIndex = 1 14 | local x,y = 1, 1 15 | function deck.addProp() 16 | local prop = Prop.new(deck) 17 | prop.deckIndex = deckIndex 18 | prop.origin = {x*32,y*32} 19 | layer.add(prop) 20 | deckIndex = deckIndex + 1 21 | x = x + 1 22 | end 23 | 24 | deck.addProp() 25 | deck.addProp() 26 | deck.addProp() 27 | deck.addProp() 28 | deck.addProp() 29 | x = 1 30 | y = 2 31 | deck.addProp() 32 | 33 | System.exit_after_seconds(0.6) 34 | end 35 | 36 | 37 | if is_main() then 38 | UnitTest.run() 39 | end 40 | -------------------------------------------------------------------------------- /Quiz/README.md: -------------------------------------------------------------------------------- 1 | Quiz 2 | ==== 3 | -------------------------------------------------------------------------------- /Quiz/test_draw_shapes.lua: -------------------------------------------------------------------------------- 1 | -- test_draw_shapes.lua 2 | -- 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'luacat' 6 | 7 | 8 | function draw_diamond(n) 9 | return "" 10 | end 11 | 12 | function draw_pyramid(n) 13 | return "" 14 | end 15 | 16 | function draw_inverted_pyramid(n) 17 | return "" 18 | end 19 | 20 | function draw_left_aligned_triangle(n) 21 | return "" 22 | end 23 | 24 | function draw_right_aligned_triangle(n) 25 | return "" 26 | end 27 | 28 | 29 | 30 | function test_draw_diamond() 31 | assert_equal([[ 32 | * 33 | *** 34 | * 35 | ]], draw_diamond(3)) 36 | end 37 | 38 | function test_draw_pyramid() 39 | assert_equal([[ 40 | * 41 | *** 42 | ***** 43 | ]], draw_pyramid(3)) 44 | end 45 | 46 | function test_draw_inverted_pyramid() 47 | assert_equal([[ 48 | ***** 49 | *** 50 | * 51 | ]], draw_inverted_pyramid(3)) 52 | end 53 | 54 | function test_draw_left_aligned_triangle() 55 | assert_equal([[ 56 | * 57 | ** 58 | *** 59 | ]], draw_left_aligned_triangle(3)) 60 | end 61 | 62 | function test_draw_right_aligned_triangle() 63 | assert_equal([[ 64 | * 65 | ** 66 | *** 67 | ]], draw_right_aligned_triangle(3)) 68 | end 69 | 70 | 71 | if is_main() then 72 | UnitTest.run() 73 | end 74 | -------------------------------------------------------------------------------- /Quiz/test_hexagon_walk.lua: -------------------------------------------------------------------------------- 1 | -- test_hexagon_walk.lua 2 | -- 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'luacat' 6 | 7 | function hexagon_walker() 8 | return { 9 | walk = function(direction) 10 | return "" 11 | end 12 | } 13 | end 14 | 15 | 16 | function test_hexagon_walk() 17 | local h = hexagon_walker() 18 | 19 | assert_equal([[ 20 | * * 21 | * @ * 22 | * * 23 | ]], h.walk()) 24 | 25 | assert_equal([[ 26 | * * 27 | * 1 * 28 | * @ * 29 | * * 30 | ]], h.walk('southeast')) 31 | 32 | assert_equal([[ 33 | * * 34 | * 1 * * 35 | * 2 @ * 36 | * * * 37 | ]], h.walk('east')) 38 | 39 | assert_equal([[ 40 | * * 41 | * 1 * * * 42 | * 2 3 @ * 43 | * * * * 44 | ]], h.walk('east')) 45 | 46 | assert_equal([[ 47 | * * 48 | * 1 * * * 49 | * 2 @ 4 * 50 | * * * * 51 | ]], h.walk('west')) 52 | 53 | assert_equal([[ 54 | * * * 55 | * 1 @ * * 56 | * 2 5 4 * 57 | * * * * 58 | ]], h.walk('northwest')) 59 | 60 | assert_equal([[ 61 | * * 62 | * @ * 63 | * 1 6 * * 64 | * 2 5 4 * 65 | * * * * 66 | ]], h.walk('northwest')) 67 | 68 | end 69 | 70 | 71 | if is_main() then 72 | UnitTest.run() 73 | end 74 | -------------------------------------------------------------------------------- /Quiz/test_indexes_to_ranges.lua: -------------------------------------------------------------------------------- 1 | -- test_indexes_to_ranges.lua 2 | -- 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'luacat' 6 | 7 | 8 | function indexes_to_ranges(indexes) 9 | local t = {} 10 | return t 11 | end 12 | 13 | 14 | function test_indexes_to_ranges() 15 | 16 | local indexes = {} 17 | assert_equal({}, indexes_to_ranges(indexes)) 18 | 19 | local indexes = {5} 20 | assert_equal({{5,1}}, indexes_to_ranges(indexes)) 21 | 22 | local indexes = {5,6,7} 23 | assert_equal({{5,3}}, indexes_to_ranges(indexes)) 24 | 25 | local indexes = {5,6,7,10,11} 26 | assert_equal({{5,3},{10,2}}, indexes_to_ranges(indexes)) 27 | 28 | local indexes = {0,1,2,3,8,9,10} 29 | assert_equal({{0,4},{8,3}}, indexes_to_ranges(indexes)) 30 | 31 | end 32 | 33 | 34 | if is_main() then 35 | UnitTest.run() 36 | end 37 | -------------------------------------------------------------------------------- /Quiz/test_obfuscation.lua: -------------------------------------------------------------------------------- 1 | -- test_obfuscation.lua 2 | -- 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'luacat' 6 | 7 | 8 | function code_obfuscate(code, names) 9 | local result = '' 10 | return result 11 | end 12 | 13 | 14 | function test_obfuscation() 15 | local code = [[ 16 | function function_a() 17 | end 18 | function function_b() 19 | function_a() 20 | end 21 | function_b() 22 | ]] 23 | local names = {'dqtgxwbrco', 'elbhgrkaoi'} 24 | local expected = [[ 25 | function dqtgxwbrco() 26 | end 27 | function elbhgrkaoi() 28 | dqtgxwbrco() 29 | end 30 | elbhgrkaoi() 31 | ]] 32 | assert_equal(expected, code_obfuscate(code, names)) 33 | end 34 | 35 | 36 | if is_main() then 37 | UnitTest.run() 38 | end 39 | -------------------------------------------------------------------------------- /Quiz/test_parse_url.lua: -------------------------------------------------------------------------------- 1 | -- test_parse_url.lua 2 | -- 3 | 4 | 5 | package.path = package.path .. ";../luacat/?.lua" 6 | require 'luacat' 7 | 8 | function parse_url(url) 9 | local t = {} 10 | return t 11 | end 12 | 13 | function parse_params(query) 14 | local t = {} 15 | return t 16 | end 17 | 18 | 19 | function test_parse_simple_url() 20 | local url = "http://google.com" 21 | local uri = parse_url(url) 22 | assert_equal("http", uri.scheme) 23 | assert_equal("google.com", uri.host) 24 | assert_equal("", uri.path) 25 | assert_equal(nil, uri.query) 26 | end 27 | 28 | function test_parse_google_search_url() 29 | local url = "http://www.google.com/search?client=safari&rls=en&q=lua&ie=UTF-8&oe=UTF-8" 30 | local uri = parse_url(url) 31 | assert_equal("http", uri.scheme) 32 | assert_equal("www.google.com", uri.host) 33 | assert_equal("/search", uri.path) 34 | assert_equal("client=safari&rls=en&q=lua&ie=UTF-8&oe=UTF-8", uri.query) 35 | local expected = { 36 | client = "safari", 37 | rls = "en", 38 | q = "lua", 39 | ie = "UTF-8", 40 | oe = "UTF-8", 41 | } 42 | assert_equal(expected, parse_params(uri.query)) 43 | end 44 | 45 | 46 | function test_parse_file_path() 47 | local url = "file:///Applications/App%20Store.app/Contents/Resources/Offline/index.html" 48 | local uri = parse_url(url) 49 | assert_equal('file', uri.scheme) 50 | assert_equal(nil, uri.host) 51 | assert_equal("/Applications/App%20Store.app/Contents/Resources/Offline/index.html", uri.path) 52 | assert_equal(nil, uri.query) 53 | end 54 | 55 | if is_main() then 56 | UnitTest.run() 57 | end 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | luacat 2 | ====== 3 | 4 | unit testing, logger, OOP, string, table extensions for lua. 5 | 6 | 7 | Unit Testing 8 | ------------ 9 | 10 | ```lua 11 | package.path = package.path .. ";../luacat/?.lua" 12 | require 'luacat' 13 | function test_luacat() 14 | assert_equal(0, 0) 15 | end 16 | if is_main() then 17 | UnitTest.run() 18 | end 19 | ``` 20 | 21 | $ lua test_luacat.lua 22 | Started 23 | . 24 | Finished in 0.0001 seconds. 25 | 1 tests, 1 assertions, 0 failures, 0 errors 26 | 27 | 28 | Logger 29 | ------ 30 | 31 | ```lua 32 | log_info( 123 ) 33 | log_info( "abc" ) 34 | log_info( {1, 2, 3} ) 35 | log_info( {a = 1, b = 2} ) 36 | log_info( "test %d %s", 123, "abc") 37 | ``` 38 | 39 | test_logger.lua:9 123 40 | test_logger.lua:10 abc 41 | test_logger.lua:11 {1, 2, 3} 42 | test_logger.lua:12 {a = 1, b = 2} 43 | test_logger.lua:13 test 123 abc 44 | 45 | 46 | OOP 47 | --- 48 | 49 | ```lua 50 | local A = extends(Object) 51 | function A.initialize(self) 52 | self.counter = 0 53 | end 54 | function A.plus_one(self) 55 | self.counter = self.counter + 1 56 | end 57 | local a = A.new() 58 | assert_equal(0, a.counter) 59 | a.plus_one() 60 | assert_equal(1, a.counter) 61 | ``` 62 | 63 | Extensions 64 | ---------- 65 | String, Table, Number, Date extensions. 66 | see TestCases. 67 | 68 | 69 | Moai Extensions 70 | --------------- 71 | luacat has also included moacat, for Moai extensions. 72 | see MoacatTestCases. 73 | 74 | 75 | Feedback 76 | -------- 77 | * Subscribe to google groups 78 | -------------------------------------------------------------------------------- /TestCases/test_all.lua: -------------------------------------------------------------------------------- 1 | -- test_all.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'test_stringext' 7 | require 'test_tableext' 8 | require 'test_numberext' 9 | require 'test_objectext' 10 | require 'test_dateext' 11 | require 'test_exception' 12 | require 'test_unittest' 13 | require 'test_casestatement' 14 | require 'test_setup_teardown' 15 | require 'test_luacat' 16 | 17 | require 'test_metatable' 18 | require 'test_coroutine' 19 | 20 | require 'test_file' 21 | require 'test_hangul' 22 | 23 | 24 | if is_main() then 25 | UnitTest.run() 26 | end 27 | -------------------------------------------------------------------------------- /TestCases/test_casestatement.lua: -------------------------------------------------------------------------------- 1 | -- test_casestatement.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'CaseStatement' 7 | 8 | function test_case() 9 | local sum = 0 10 | case('a', 11 | 'a', function() sum = sum + 1 end, 12 | 'b', function() sum = sum + 2 end 13 | ) 14 | assert_equal(1, sum) 15 | 16 | local sum = 0 17 | case('b', 18 | 'a', function() sum = sum + 1 end, 19 | 'b', function() sum = sum + 2 end 20 | ) 21 | assert_equal(2, sum) 22 | 23 | local sum = 0 24 | case(1, 25 | 1, function() sum = sum + 1 end, 26 | 2, function() sum = sum + 2 end 27 | ) 28 | assert_equal(1, sum) 29 | end 30 | 31 | function test_case_default() 32 | local sum = 0 33 | case(100, 34 | 1, function() sum = sum + 1 end 35 | ) 36 | assert_equal(0, sum) 37 | 38 | local sum = 0 39 | case(100, 40 | 1, function() sum = sum + 1 end, 41 | function() sum = sum + 5 end 42 | ) 43 | assert_equal(5, sum) 44 | end 45 | 46 | function test_case_duplicated() 47 | local sum = 0 48 | case('a', 49 | 'a', function() sum = sum + 1 end, 50 | 'a', function() sum = sum + 1 end 51 | ) 52 | assert_equal(1, sum) 53 | end 54 | 55 | function test_match_case() 56 | local sum = 0 57 | match_case('abc', 58 | 'a*', function() sum = sum + 1 end, 59 | 'd*', function() sum = sum + 2 end 60 | ) 61 | assert_equal(1, sum) 62 | 63 | local sum = 0 64 | match_case('abc', 65 | 'd*', function() sum = sum + 2 end, 66 | function() sum = sum + 5 end 67 | ) 68 | assert_equal(5, sum) 69 | end 70 | 71 | function test_case_result() 72 | local result = case(1, 73 | 1, function() return 1 end 74 | ) 75 | assert_equal(1, result) 76 | 77 | local result = match_case('/', 78 | "/a+", function() return 'a' end, 79 | "/b+", function() return 'b' end, 80 | function() return 'c' end 81 | ) 82 | assert_equal('c', result) 83 | 84 | local result = match_case(nil, 85 | "/a+", function() return 'a' end, 86 | function() return 'c' end 87 | ) 88 | assert_equal('c', result) 89 | end 90 | 91 | if is_main() then 92 | UnitTest.run() 93 | end 94 | -------------------------------------------------------------------------------- /TestCases/test_coroutine.lua: -------------------------------------------------------------------------------- 1 | -- test_coroutine.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'Logger' 7 | 8 | -- Coroutines in Lua.pdf 9 | function test_coroutine_wrap() 10 | local co = coroutine.wrap(function(a) 11 | local c = coroutine.yield(a + 2) 12 | return c * 2 end 13 | ) 14 | 15 | local b = co(20) 16 | assert_equal(22, b) 17 | 18 | local d = co(b + 1) 19 | assert_equal(46, d) 20 | end 21 | 22 | function test_preorder() 23 | 24 | function preorder(node) 25 | if node then 26 | preorder(node.left) 27 | coroutine.yield(node.key) 28 | preorder(node.right) 29 | end 30 | end 31 | 32 | function preorder_iterator(tree) 33 | return coroutine.wrap( 34 | function() 35 | preorder(tree) 36 | end) 37 | end 38 | 39 | function merge(t1, t2) 40 | local it1 = preorder_iterator(t1) 41 | local it2 = preorder_iterator(t2) 42 | local v1 = it1() 43 | local v2 = it2() 44 | while v1 or v2 do 45 | if v1 ~= nil and (v2 == nil or v1 < v2) then 46 | print(v1); v1 = it1() 47 | else 48 | print(v2); v2 = it2() 49 | end 50 | end 51 | end 52 | end 53 | 54 | 55 | if is_main() then 56 | UnitTest.run() 57 | end 58 | -------------------------------------------------------------------------------- /TestCases/test_dateext.lua: -------------------------------------------------------------------------------- 1 | -- test_dateext.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'DateExt' 7 | 8 | function test_date() 9 | 10 | local date = Date.new(2010,1,1) 11 | assert_equal(2010, date.year) 12 | assert_equal(1, date.month) 13 | assert_equal(1, date.day) 14 | assert_equal(0, date.hour) 15 | assert_equal(0, date.min) 16 | assert_equal(0, date.sec) 17 | 18 | local yesterday = date.yesterday 19 | assert_equal(2009, yesterday.year) 20 | assert_equal(12, yesterday.month) 21 | assert_equal(31, yesterday.day) 22 | 23 | assert_equal(date, yesterday.tomorrow) 24 | assert_equal(86400, _(1).days) 25 | assert_equal(yesterday, date.before(_(1).days)) 26 | assert_equal(date, yesterday.after(_(1).days)) 27 | 28 | local today = Date.today() 29 | local diff = today - date 30 | local days_repr = time_interval_to_days(diff) 31 | assert_one_of(Table.keys(days_repr), 'days') 32 | 33 | assert_true(2011 <= today.year) 34 | assert_true(date < today) 35 | assert_true(date <= today) 36 | assert_false(date > today) 37 | assert_false(date >= today) 38 | assert_false(date == today) 39 | assert_true(date ~= today) 40 | 41 | assert_equal(_(24).hours, _(1).days) 42 | assert_equal(_(60).minutes, _(1).hours) 43 | assert_equal(_(60).seconds, _(1).minutes) 44 | 45 | assert_one_of(_(date).methods(), 'today') 46 | assert_one_of(_(date).methods(), 'before') 47 | 48 | end 49 | 50 | function test_time() 51 | assert_equal(Time.milliseconds(1000), Time.seconds(1)) 52 | end 53 | 54 | 55 | if is_main() then 56 | UnitTest.run() 57 | end 58 | -------------------------------------------------------------------------------- /TestCases/test_exception.lua: -------------------------------------------------------------------------------- 1 | -- test_exception.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'Exception' 7 | 8 | function test_exception() 9 | 10 | local raised = 0 11 | try(function() string.format("%s", nil) end, 12 | function(e) raised = raised + 1 end) 13 | assert_equal(1, raised) 14 | 15 | assert_raise("bad argument #2 to 'format'", 16 | function() string.format("%s", nil) end) 17 | end 18 | 19 | if is_main() then 20 | UnitTest.run() 21 | end 22 | -------------------------------------------------------------------------------- /TestCases/test_file.lua: -------------------------------------------------------------------------------- 1 | -- test_file.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'File' 7 | 8 | function test_file() 9 | 10 | local f = File.open('test_file.lua') 11 | local content = f.read() 12 | assert_true(332 < #content) 13 | f.close() 14 | 15 | local f = File.open('test_file.lua') 16 | local lines = f.readlines() 17 | assert_true(24 < #lines) 18 | f.close() 19 | 20 | end 21 | 22 | 23 | if is_main() then 24 | UnitTest.run() 25 | end 26 | -------------------------------------------------------------------------------- /TestCases/test_hangul.lua: -------------------------------------------------------------------------------- 1 | -- test_hangul.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'Hangul' 7 | 8 | 9 | function test_string_to_uchars() 10 | local str = "a가b나" 11 | assert_equal(8, #str) 12 | local uchars = string_to_uchars(str) 13 | assert_equal(4, #uchars) 14 | assert_equal({"a", "가", "b", "나"}, uchars) 15 | assert_equal("a가b나", uchars_to_string(uchars)) 16 | end 17 | 18 | function test_hangul_chosungs() 19 | assert_equal({"a", "ㄱ", "b", "ㄴ"}, hangul_chosungs("a가b나")) 20 | assert_equal({"ㄱ", "ㄴ", "ㄷ"}, hangul_chosungs("가나다")) 21 | end 22 | 23 | function test_hangul_split_join() 24 | assert_equal({"ㄱ", "ㅏ", EMPTY}, hangul_split("가")) 25 | assert_equal({"ㅎ", "ㅏ", "ㄴ"}, hangul_split("한")) 26 | assert_equal({"ㄱ", "ㅡ", "ㄹ"}, hangul_split("글")) 27 | assert_equal("가", hangul_join({"ㄱ", "ㅏ", EMPTY})) 28 | assert_equal("한", hangul_join({"ㅎ", "ㅏ", "ㄴ"})) 29 | assert_equal("글", hangul_join({"ㄱ", "ㅡ", "ㄹ"})) 30 | end 31 | 32 | function test_group_by_chosung() 33 | local words = {'감자','마늘','고구마'} 34 | local group = group_by_chosung(words) 35 | assert_equal( 36 | { ['ㄱ'] = { '감자', '고구마'}, ['ㅁ'] = { '마늘' }}, 37 | group) 38 | end 39 | 40 | function test_hangul_search() 41 | local words = {'감자','마늘','고구마'} 42 | assert_equal({'감자', '고구마'}, hangul_search(words, 'ㄱ')) 43 | assert_equal({'감자'}, hangul_search(words, '가')) 44 | assert_equal({'감자'}, hangul_search(words, '감')) 45 | assert_equal({'감자'}, hangul_search(words, '감ㅈ')) 46 | assert_equal({'고구마'}, hangul_search(words, '구')) 47 | end 48 | 49 | if is_main() then 50 | UnitTest.run() 51 | end 52 | -------------------------------------------------------------------------------- /TestCases/test_logger.lua: -------------------------------------------------------------------------------- 1 | -- test_logger.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'Logger' 6 | require 'StringExt' 7 | 8 | 9 | log_info( nil ) 10 | log_info( 123 ) 11 | log_info( "abc" ) 12 | log_info( {1, 2, 3} ) 13 | log_info( {a = 1, b = 2} ) 14 | log_info( "test %d %s", 123, "abc") 15 | log_info( "test nil : %s", to_s(nil) ) 16 | log_info( "test {1} : %s", {1} ) 17 | log_info( "test {a=1} {b=2} : %s %s", {a=1}, {b=2}) 18 | log_info( {a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, i=9, j=10, k=11} ) 19 | log_info( "abc", {1, 2, 3} ) 20 | log_info( {1, 2, 3}, "abc" ) 21 | log_info( {{1, 2}, {3, 4}} ) 22 | 23 | 24 | -- custom 25 | function log_ui(ui) 26 | log_info('UI', ui) 27 | end 28 | 29 | log_ui( 'shape' ) -- test_logger.lua:29 UI shape 30 | 31 | 32 | -- __tostring 33 | local mt = { 34 | __tostring = function() 35 | return '' 36 | end 37 | } 38 | local m = {} 39 | setmetatable(m, mt) 40 | log_info(m) 41 | 42 | 43 | --[[ 44 | test_logger.lua:9 nil 45 | test_logger.lua:10 123 46 | test_logger.lua:11 abc 47 | test_logger.lua:12 {1, 2, 3} 48 | test_logger.lua:13 {a = 1, b = 2} 49 | test_logger.lua:14 test 123 abc 50 | test_logger.lua:15 test nil : nil 51 | test_logger.lua:16 test {1} : {1} 52 | test_logger.lua:17 test {a=1} {b=2} : {a = 1} {b = 2} 53 | test_logger.lua:18 { a = 1, 54 | b = 2, 55 | c = 3, 56 | d = 4, 57 | e = 5, 58 | f = 6, 59 | g = 7, 60 | h = 8, 61 | i = 9, 62 | j = 10, 63 | k = 11} 64 | test_logger.lua:19 abc {1, 2, 3} 65 | test_logger.lua:20 {1, 2, 3} abc 66 | test_logger.lua:21 {{1, 2}, {3, 4}} 67 | test_logger.lua:29 UI shape 68 | test_logger.lua:40 69 | --]] 70 | -------------------------------------------------------------------------------- /TestCases/test_luacat.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path .. ";../luacat/?.lua" 2 | require 'luacat' 3 | 4 | function test_luacat() 5 | assert_equal(0, 0) 6 | end 7 | 8 | 9 | if is_main() then 10 | UnitTest.run() 11 | end 12 | -------------------------------------------------------------------------------- /TestCases/test_metatable.lua: -------------------------------------------------------------------------------- 1 | -- test_all.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'Logger' 7 | 8 | function test_metatable() 9 | local dict = { a = 2 } 10 | assert_nil(getmetatable(dict)) 11 | 12 | setmetatable(dict, {}) 13 | 14 | local mt = getmetatable(dict) 15 | assert_equal({}, mt) 16 | 17 | assert_nil(getmetatable(nil)) 18 | assert_nil(getmetatable(1)) 19 | end 20 | 21 | if is_main() then 22 | UnitTest.run() 23 | end 24 | -------------------------------------------------------------------------------- /TestCases/test_numberext.lua: -------------------------------------------------------------------------------- 1 | -- test_numberext.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'NumberExt' 7 | require 'Logger' 8 | 9 | function test_number() 10 | assert_equal("number", type(1)) 11 | assert_equal("a", int_to_char(97)) 12 | assert_equal(97, char_to_int("a")) 13 | assert_equal("1", to_s(1)) 14 | 15 | assert_equal(1, string_to_int("1")) 16 | assert_equal(3.14, string_to_float("3.14")) 17 | assert_equal(1.2, string_to_float("1.2.3")) 18 | assert_true(3.141592653589 < PI) 19 | 20 | assert_false(_(0).is_odd()) 21 | assert_true(_(1).is_odd()) 22 | assert_false(is_odd(0)) 23 | assert_true(is_odd(1)) 24 | assert_false(is_odd(2)) 25 | assert_true(is_odd(3)) 26 | 27 | assert_one_of(_(1).methods(), 'is_odd') 28 | 29 | local random = get_random(2) 30 | assert_true(0 <= random) 31 | end 32 | 33 | function test_number_block() 34 | local ary = {} 35 | _(3).times(function(n) 36 | table.insert(ary, n) 37 | end) 38 | assert_equal({1,2,3}, ary) 39 | 40 | local ary = {} 41 | _(1).upto(3, function(n) 42 | table.insert(ary, n) 43 | end) 44 | assert_equal({1,2,3}, ary) 45 | 46 | local ary = {} 47 | _(3).downto(1, function(n) 48 | table.insert(ary, n) 49 | end) 50 | assert_equal({3,2,1}, ary) 51 | end 52 | 53 | 54 | 55 | if is_main() then 56 | UnitTest.run() 57 | end 58 | -------------------------------------------------------------------------------- /TestCases/test_objectext.lua: -------------------------------------------------------------------------------- 1 | -- test_objectext.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'ObjectExt' 7 | require 'Logger' 8 | 9 | function test_extends() 10 | local A = extends(Object) 11 | function A.func_a(self) 12 | return 'A' 13 | end 14 | assert_nil(Object.superclass) 15 | assert_equal(Object, A.superclass) 16 | local a = A.new() 17 | a.name = 'a name' 18 | assert_equal(A, a.class) 19 | assert_equal(A.mt, getmetatable(a)) 20 | assert_equal('a name', a.name) 21 | assert_equal('A', a.func_a()) 22 | function a.func_a(self) 23 | return 'a' 24 | end 25 | assert_equal('a', a.func_a()) 26 | 27 | local B = extends(A) 28 | assert_equal(A, B.superclass) 29 | local b = B.new() 30 | assert_equal(B, b.class) 31 | assert_equal('A', b.func_a()) 32 | function b.func_a(self) 33 | return 'b' 34 | end 35 | assert_equal('b', b.func_a()) 36 | 37 | local C = extends(B) 38 | assert_equal(B, C.superclass) 39 | local c = C.new() 40 | assert_equal(C, c.class) 41 | assert_equal('A', c.func_a()) 42 | function c.func_a(self) 43 | return 'c' 44 | end 45 | assert_equal('c', c.func_a()) 46 | 47 | function B.func_a(self) 48 | return 'B' 49 | end 50 | local b2 = B.new() 51 | assert_equal('B', b2.func_a()) 52 | 53 | function C.func_a(self) 54 | return 'C' 55 | end 56 | local c2 = C.new() 57 | assert_equal('C', c2.func_a()) 58 | end 59 | 60 | 61 | function test_initialize() 62 | local A = extends(Object) 63 | function A.initialize(self) 64 | self.counter = 0 65 | end 66 | function A.plus_one(self) 67 | self.counter = self.counter + 1 68 | end 69 | local a = A.new() 70 | assert_equal(0, a.counter) 71 | a.plus_one() 72 | assert_equal(1, a.counter) 73 | end 74 | 75 | function test_initialize_with_arguments() 76 | local A = extends(Object) 77 | function A.initialize(self, init) 78 | self.counter = init 79 | end 80 | function A.plus_one(self) 81 | self.counter = self.counter + 1 82 | end 83 | local a = A.new(5) 84 | local a2 = A.new(5) 85 | assert_equal(5, a.counter) 86 | a.plus_one() 87 | assert_equal(6, a.counter) 88 | assert_equal(5, a2.counter) 89 | a2.plus_one() 90 | assert_equal(6, a2.counter) 91 | end 92 | 93 | function test_subclass_initialize_with_arguments() 94 | local A = extends(Object) 95 | function A.initialize(self, init) 96 | self.counter = init 97 | end 98 | local B = extends(A) 99 | local b = B.new(5) 100 | assert_equal(5, b.counter) 101 | end 102 | 103 | 104 | function test_is_nil() 105 | assert_true(_(nil).is_nil()) 106 | assert_false(_(nil).is_not_nil()) 107 | assert_false(_(0).is_nil()) 108 | assert_true(_(0).is_not_nil()) 109 | 110 | assert_nil(nil) 111 | assert_not_nil(not nil) 112 | assert_true(is_nil(nil)) 113 | assert_true(is_not_nil(0)) 114 | end 115 | 116 | function test_methods() 117 | local klass = extends(Object) 118 | function klass.func() 119 | return 1 120 | end 121 | function klass.func2() 122 | return 2 123 | end 124 | assert_one_of(Object.methods(klass), 'func') 125 | assert_one_of(_(klass).methods(), 'func') 126 | assert_equal(klass.func, _(klass).method('func')) 127 | assert_equal(klass.func, Object.method(klass, 'func')) 128 | assert_equal(1, Object.method(klass, 'func')()) 129 | end 130 | 131 | function test_import() 132 | local Color = extends(Object) 133 | local colorMap = { 134 | red = {255, 0, 0}, 135 | green = {0, 255, 0}, 136 | blue = {0, 0, 255}, 137 | is_red = function(rgb) 138 | return Table.equal({255,0,0}, rgb) 139 | end 140 | } 141 | Color.import(colorMap) 142 | assert_equal({255,0,0}, Color.red) 143 | assert_equal({0,255,0}, Color.green) 144 | assert_equal({0,0,255}, Color.blue) 145 | assert_true(Color.is_red({255,0,0})) 146 | assert_false(Color.is_red({0,255,0})) 147 | end 148 | 149 | function test_getter_setter() 150 | local A = extends(Object) 151 | function A.getColor(self) 152 | return self._color 153 | end 154 | function A.setColor(self, color) 155 | self._color = Table.concat(color, {255}) 156 | end 157 | local a = A.new() 158 | a.color = {0,0,0} 159 | assert_equal({0,0,0,255}, a.color) 160 | 161 | local B = extends(A) 162 | local b = B.new() 163 | b.color = {0,0,1} 164 | assert_equal({0,0,1,255}, b.color) 165 | end 166 | 167 | function test_getter_setter_self() 168 | local A = extends(Object) 169 | function A.three(self) 170 | return 3 171 | end 172 | function A.getNum(self) 173 | return self._num + self.three() 174 | end 175 | function A.setNum(self, n) 176 | self._num = n + self.three() 177 | end 178 | local a = A.new() 179 | a.num = 1 180 | assert_equal(7, a.num) 181 | end 182 | 183 | function test_synthesize() 184 | local A = extends(Object) 185 | function A.initialize(self) 186 | self.person = { name = 'Finn', age = 15 } 187 | end 188 | A.synthesize({'name','age'}, function(self) return self.person end) 189 | local a = A.new() 190 | assert_equal('Finn', a.person.name) 191 | assert_equal('Finn', a.name) 192 | a.name = 'Jake' 193 | assert_equal('Jake', a.person.name) 194 | assert_equal('Jake', a.name) 195 | assert_equal(15, a.age) 196 | end 197 | 198 | function test_wrap_synthesize() 199 | local A = extends(Object) 200 | function A:initialize() 201 | self.value = 1 202 | end 203 | function A:getVal() 204 | return self.value 205 | end 206 | function A:setVal(val) 207 | self.value = val 208 | end 209 | local B = extends(Object) 210 | function B.initialize(self) 211 | self.wrap = A.new() 212 | end 213 | B.wrap_synthesize({'val'}) 214 | 215 | local b = B.new() 216 | assert_equal(1, b.val) 217 | end 218 | 219 | function test_lua_object() 220 | assert_equal(3, ("abc"):len()) 221 | assert_equal(3, _("abc"):length()) 222 | assert_equal(3, _("abc").length()) 223 | 224 | assert_equal("ABC", ("abc"):upper()) 225 | assert_equal("ABC", _("abc"):upcase()) 226 | assert_equal("ABC", _("abc").upcase()) 227 | end 228 | 229 | function test_self_call_in_initialize() 230 | local A = extends(Object) 231 | function A.initialize(self) 232 | self.name = self.func_a() 233 | end 234 | function A.func_a(self) 235 | return "A" 236 | end 237 | local a = A.new() 238 | assert_equal("A", a.name) 239 | assert_true(a.is_a(A)) 240 | 241 | local B = extends(A) 242 | local b = B.new() 243 | assert_true(b.is_a(B)) 244 | assert_true(b.is_a(A)) 245 | end 246 | 247 | if is_main() then 248 | UnitTest.run() 249 | end 250 | -------------------------------------------------------------------------------- /TestCases/test_setup_teardown.lua: -------------------------------------------------------------------------------- 1 | -- test_setup_teardown.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | 7 | local TestBox = {} 8 | 9 | function TestBox.setup(self) 10 | self.base = 1 11 | end 12 | 13 | function TestBox.teardown(self) 14 | self.base = 0 15 | end 16 | 17 | function TestBox.test_one_time(self) 18 | assert_equal(2, self.base + 1) 19 | end 20 | 21 | function TestBox.test_two_time(self) 22 | assert_equal(2, self.base + 1) 23 | end 24 | 25 | 26 | function test_testbox() 27 | UnitTest.run(TestBox) 28 | end 29 | 30 | if is_main() then 31 | UnitTest.run() 32 | end 33 | -------------------------------------------------------------------------------- /TestCases/test_stringext.lua: -------------------------------------------------------------------------------- 1 | -- test_stringext.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'StringExt' 7 | require 'Logger' 8 | 9 | function test_string_multiline() 10 | local str = [[ 11 | a 12 | b 13 | ]] 14 | assert_equal("a\nb\n", str) 15 | end 16 | 17 | function test_string() 18 | 19 | assert_equal("b", _("abcde").slice(2,2)) 20 | 21 | assert_equal("b", String.slice("abcde", 2,2)) 22 | assert_equal("bc", String.slice("abcde", 2,3)) 23 | assert_equal("bcde", String.slice("abcde", 2,-1)) 24 | 25 | assert_equal("abc", String.strip("\n abc")) 26 | assert_equal("abc", _("\n abc").strip()) 27 | 28 | local str = " a b c " 29 | assert_equal("a b c", String.strip(str)) 30 | assert_equal("a b c ", String.lstrip(str)) 31 | assert_equal(" a b c", String.rstrip(str)) 32 | 33 | assert_equal({"a", "b", "c"}, String.split("a b c", SPACE)) 34 | assert_equal({"a", "b", "c"}, _("a b c").split(SPACE)) 35 | 36 | assert_equal(3, String.length("abc")) 37 | assert_equal("cba", String.reverse("abc")) 38 | assert_equal("ABC", String.upcase("abc")) 39 | assert_equal("abc", String.downcase("ABC")) 40 | 41 | assert_equal("", String.capitalize("")) 42 | assert_equal("A", String.capitalize("a")) 43 | assert_equal("Abc", String.capitalize("abc")) 44 | 45 | assert_equal("abc def", SWF("abc %s", "def")) 46 | assert_equal("0xff", SWF("0x%x", 255)) 47 | 48 | assert_true(String.start_with("hello", "he")) 49 | assert_false(String.start_with("hello", "lo")) 50 | assert_true(String.end_with("", "")) 51 | assert_false(String.end_with("", "a")) 52 | assert_true(String.end_with("hello", "")) 53 | assert_true(String.end_with("hello", "lo")) 54 | assert_false(String.end_with("hello", "he")) 55 | assert_true(String.include("hello", "lo")) 56 | assert_false(String.include("hello", "loo")) 57 | 58 | assert_equal({"a","b","c"}, _w("a b c")) 59 | assert_equal("abcd", string.gsub("abcff","ff","d")) 60 | 61 | assert_true(String.is_empty("")) 62 | assert_false(String.is_empty(" ")) 63 | assert_not_empty(" ") 64 | assert_not_empty("\n") 65 | assert_empty("") 66 | 67 | assert_equal(2, String.count("hello", "l")) 68 | assert_equal(1, String.count("hello", "ll")) 69 | assert_equal(0, String.count("hello", "lll")) 70 | 71 | assert_false(_("").is_nil()) 72 | assert_true(_("").is_not_nil()) 73 | assert_one_of(_("").methods(), 'split') 74 | 75 | assert_equal("apple", String.gsub("abc", "bc", "pple")) 76 | 77 | local str = 'a' 78 | assert_equal("ab", String.concat(str, 'b')) 79 | assert_equal("a", str) -- immutable 80 | assert_equal("aaaaa", _('a') * 5) 81 | assert_equal("ababab", _('ab') * 3) 82 | end 83 | 84 | function test_to_s() 85 | assert_equal("nil", to_s(nil)) 86 | assert_equal("{}", to_s({})) 87 | assert_equal("{}", to_s({nil})) 88 | function multiple(...) 89 | return ... 90 | end 91 | assert_equal("1, 2", to_s(1, 2)) 92 | assert_equal("1, 2", to_s(multiple(1,2))) 93 | end 94 | 95 | 96 | if is_main() then 97 | UnitTest.run() 98 | end 99 | -------------------------------------------------------------------------------- /TestCases/test_tableext.lua: -------------------------------------------------------------------------------- 1 | -- test_tableext.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | require 'TableExt' 7 | require 'Logger' 8 | 9 | function test_nil() 10 | assert_equal(0, #{nil}) 11 | assert_equal({}, {nil}) 12 | end 13 | 14 | function test_lua_table() 15 | local a = {1,2,3} 16 | a[3] = 5 17 | a[10] = 5 18 | a['b'] = 5 19 | a.c = 5 20 | 21 | local cnt = 0 22 | for k,v in ipairs(a) do 23 | cnt = cnt + 1 24 | end 25 | assert_equal(3, cnt) 26 | 27 | cnt = 0 28 | for k,v in pairs(a) do 29 | cnt = cnt + 1 30 | end 31 | assert_equal(6, cnt) 32 | 33 | assert_equal(6, Table.count(a)) 34 | a.c = nil 35 | assert_equal(5, Table.count(a)) 36 | end 37 | 38 | 39 | function test_array() 40 | 41 | local array = {1,2,3,4,5} 42 | assert_equal({1}, Table.slice(array, 0, 1)) 43 | assert_equal({1}, Table.slice(array, 1, 1)) 44 | assert_equal({1,2}, Table.slice(array, 1, 2)) 45 | assert_equal({2,3}, Table.slice(array, 2, 3)) 46 | assert_equal({2,3,4}, Table.slice(array, 2, -2)) 47 | assert_equal({2,3,4,5}, Table.slice(array, 2, -1)) 48 | assert_equal("1 2 3 4 5", Table.join(array, " ")) 49 | assert_equal("1, 2, 3, 4, 5", Table.join(array, ", ")) 50 | assert_equal({5,4,3,2,1}, Table.reverse(array)) 51 | assert_equal({1,2,3,4,5}, Table.to_a(array)) 52 | 53 | assert_equal(1, Table.index({5,6}, 5)) 54 | assert_equal(nil, Table.index({5,6}, 7)) 55 | 56 | local pushed = Table.push(array, 6) 57 | assert_equal({1,2,3,4,5,6}, array) 58 | assert_equal({1,2,3,4,5,6}, pushed) 59 | 60 | local popped = Table.pop(array) 61 | assert_equal(6, popped) 62 | assert_equal({1,2,3,4,5}, array) 63 | 64 | local popped = Table.pop(array, 0) 65 | assert_equal({}, popped) 66 | assert_equal({1,2,3,4,5}, array) 67 | 68 | local popped = Table.pop(array, 1) 69 | assert_equal({5}, popped) 70 | assert_equal({1,2,3,4}, array) 71 | 72 | local popped = Table.pop(array, 2) 73 | assert_equal({3,4}, popped) 74 | assert_equal({1,2}, array) 75 | 76 | local popped = Table.pop(array, 3) 77 | assert_equal({1,2}, popped) 78 | assert_equal({}, array) 79 | 80 | local pushed = Table.push(array, 6,7,8) 81 | assert_equal({6,7,8}, pushed) 82 | assert_equal({6,7,8}, array) 83 | 84 | assert_equal({}, Table.reverse({})) 85 | assert_equal({2,4,6}, Table.map({1,2,3}, function(x) return x*2 end)) 86 | assert_equal({2,4,6}, Table.map_with_index({1,2,3}, function(x,idx) return x + idx end)) 87 | assert_equal({1,2}, Table.select({1,2,3}, function(x) return x<=2 end)) 88 | assert_equal({3}, Table.reject({1,2,3}, function(x) return x<=2 end)) 89 | assert_equal(8, Table.reduce({1,2,3}, 2, function(result,x) return result + x end)) 90 | 91 | local unsorted = {2, 3, 1} 92 | assert_equal({1,2,3}, Table.sort(unsorted)) 93 | assert_equal({2,3,1}, unsorted) 94 | 95 | assert_equal({1,2,3}, Table.sort({2,3,1}, function(a,b) return a < b end)) 96 | assert_equal({3,2,1}, Table.sort({2,3,1}, function(a,b) return a > b end)) 97 | 98 | local result = {} 99 | Table.each({1,2,3}, function(x) Table.push(result, x) end) 100 | assert_equal({1,2,3}, result) 101 | result = {} 102 | Table.each_with_index({5,6,7}, function(x,idx) result[idx] = x end) 103 | assert_equal({5,6,7}, result) 104 | 105 | assert_true(Table.include({1,2,3}, 1)) 106 | assert_false(Table.include({1,2,3}, 0)) 107 | 108 | assert_empty({}) 109 | assert_not_empty({1}) 110 | 111 | assert_equal(5, Table.count({1,2,3,3,5})) 112 | assert_equal(2, Table.count({1,2,3,3,5}, 3)) 113 | 114 | assert_one_of(_({}).methods(), 'count') 115 | 116 | local a = {1,2} 117 | assert_equal({1,2,3,4}, Table.concat(a, {3,4})) 118 | assert_equal({1,2,3,4}, a) 119 | 120 | local cnt = 0 121 | for idx = 0, 10 do 122 | local shuffled_one = Table.shuffle(a) 123 | local shuffled_two = Table.shuffle(a) 124 | if Table.equal(shuffled_one, shuffled_two) then 125 | cnt = cnt + 1 126 | end 127 | end 128 | assert_true(5 > cnt) 129 | assert_equal({1,2,3,4}, a) 130 | 131 | Table.clear(a) 132 | assert_equal({}, a) 133 | 134 | assert_equal({5,5,5}, _({5}) * 3) 135 | assert_equal({1,2,1,2,1,2}, _({1,2}) * 3) 136 | end 137 | 138 | function test_inject() 139 | local result = Table.inject({1,2,3}, 0, function(result, e) 140 | return result + e 141 | end) 142 | assert_equal(6, result) 143 | local result = Table.inject({'a','b','c'}, '', function(result, e) 144 | return result .. e 145 | end) 146 | assert_equal("abc", result) 147 | local result = Table.inject({'a','b','c'}, {}, function(result, e) 148 | table.insert(result, e) 149 | return result 150 | end) 151 | assert_equal({'a','b','c'}, result) 152 | end 153 | 154 | function test_each_slice_each_cons() 155 | local ary = {1,2,3,4,5,6,7,8,9,10} 156 | local groups = {} 157 | Table.each_slice(ary, 3, function(a) 158 | table.insert(groups, a) 159 | end) 160 | assert_equal({{1,2,3}, {4,5,6}, {7,8,9}, {10}}, groups) 161 | local groups = {} 162 | Table.each_cons(ary, 3, function(a) 163 | table.insert(groups, a) 164 | end) 165 | assert_equal({{1,2,3}, {2,3,4}, {3,4,5}, {4,5,6}, {5,6,7}, {6,7,8}, {7,8,9}, {8,9,10}}, groups) 166 | 167 | local ary = {1,2,3,4} 168 | local groups = {} 169 | Table.each_slice(ary, 3, function(a) 170 | table.insert(groups, a) 171 | end) 172 | assert_equal({{1,2,3}, {4}}, groups) 173 | local groups = {} 174 | Table.each_cons(ary, 3, function(a) 175 | table.insert(groups, a) 176 | end) 177 | assert_equal({{1,2,3},{2,3,4}}, groups) 178 | end 179 | 180 | function test_dictionary() 181 | assert_equal({}, {a,b,c}) 182 | 183 | local dict = { a = 'apple', b = 'banana' } 184 | assert_equal({'a','b'}, Table.keys(dict)) 185 | assert_equal({'apple','banana'}, Table.values(dict)) 186 | assert_equal(2, Table.count(dict)) 187 | assert_equal({{'a','apple'},{'b','banana'}}, Table.to_a(dict)) 188 | 189 | local merged = Table.merge(dict, {c='cat'}) 190 | assert_equal(2, Table.count(dict)) 191 | assert_equal(3, Table.count(merged)) 192 | assert_equal({'a','b','c'}, Table.sort(Table.keys(merged))) 193 | 194 | assert_true(Table.has_key({a=1}, 'a')) 195 | assert_false(Table.has_key({a=1}, 'b')) 196 | 197 | assert_true(_({a=1}).has_key('a')) 198 | 199 | local result = {} 200 | Table.each({a=1,b=2,c=3}, function(k,v) Table.push(result, {k,v}) end) 201 | --assert_equal({{'a',1},{'b',2},{'c',3}}, result) 202 | 203 | local dict = { one = "uno", two = "dos", three = "tres", zz = "dos"} 204 | assert_equal({'two',"dos"}, Table.assoc(dict, 'two')) 205 | --assert_equal({'two',"dos"}, Table.rassoc(dict, 'dos')) 206 | 207 | Table.clear(dict) 208 | assert_equal({}, dict) 209 | 210 | assert_equal({a=1, b=2}, Hash({{'a',1},{'b',2}})) 211 | end 212 | 213 | function test_each() 214 | local sum = 0 215 | local ary = {1,2,3} 216 | for e in each(ary) do 217 | sum = sum + e 218 | end 219 | assert_equal(6, sum) 220 | 221 | local keys = {} 222 | local values = {} 223 | local dict = { name = 'sejong', age = 20} 224 | for k,v in each(dict) do 225 | table.insert(keys, k) 226 | table.insert(values, v) 227 | end 228 | assert_equal({'name', 'age'}, keys) 229 | assert_equal({'sejong', 20}, values) 230 | end 231 | 232 | function test_sorted_each() 233 | local dict = { name = 'sejong', age = 20} 234 | local keys = {} 235 | for k,v in sorted_each(dict) do 236 | table.insert(keys, k) 237 | end 238 | assert_equal({'age', 'name'}, keys) 239 | end 240 | 241 | function test_sorted_each_key_has_table() 242 | local dict = { [{2}] = 'sejong', [{1}] = 'king', [{12}] = 20} 243 | local keys = {} 244 | for k,v in sorted_each(dict) do 245 | table.insert(keys, k) 246 | end 247 | assert_equal({{1},{2},{12}}, keys) 248 | end 249 | 250 | function test_table_new() 251 | assert_equal({}, Table.new()) 252 | assert_equal({'*','*','*'}, Table.new(3, '*')) 253 | end 254 | 255 | function test_table_at() 256 | assert_equal(nil, Table.at({5,6}, 0)) 257 | assert_equal(5, Table.at({5,6}, 1)) 258 | assert_equal(6, Table.at({5,6}, 2)) 259 | assert_equal(nil, Table.at({5,6}, 3)) 260 | assert_equal(6, Table.at({5,6}, -1)) 261 | assert_equal(5, Table.at({5,6}, -2)) 262 | assert_equal(nil, Table.at({5,6}, -3)) 263 | end 264 | 265 | function test_table_delete_at() 266 | local ary = {5,6,7} 267 | assert_equal(5, Table.delete_at(ary, 1)) 268 | assert_equal({6,7}, ary) 269 | end 270 | 271 | function test_table_flatten() 272 | local t = {1,{2, {3,4}, 5}} 273 | assert_equal({1,2,3,4,5}, Table.flatten(t)) 274 | end 275 | 276 | if is_main() then 277 | UnitTest.run() 278 | end 279 | -------------------------------------------------------------------------------- /TestCases/test_unittest.lua: -------------------------------------------------------------------------------- 1 | -- test_unittest.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'UnitTest' 6 | 7 | function test_unittest() 8 | assert_equal( 1, 1 ) 9 | assert_equal( {1}, {1} ) 10 | 11 | assert_true( true ) 12 | assert_false( false ) 13 | assert_nil( nil ) 14 | assert_not_nil(not nil) 15 | assert_true(not nil) 16 | 17 | assert_not_empty("a") 18 | assert_one_of({1,2}, 1) 19 | 20 | -- test fail 21 | -- assert_equal( 1, 2 ) 22 | -- assert_equal( "", {2} ) 23 | end 24 | 25 | 26 | function test_return_values() 27 | function twovalues() 28 | return 1,2 29 | end 30 | 31 | local a = twovalues() 32 | assert_equal(1, a) 33 | 34 | local a,b = twovalues() 35 | assert_equal(1, a) 36 | assert_equal(2, b) 37 | end 38 | 39 | if is_main() then 40 | UnitTest.run() 41 | end 42 | -------------------------------------------------------------------------------- /luacat/CaseStatement.lua: -------------------------------------------------------------------------------- 1 | -- CaseStatement.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'TableExt' 5 | 6 | function case(target, ...) 7 | local rest = {...} 8 | local n = 2 9 | for idx=1, #rest, n do 10 | local pair = Table.slice(rest, idx, idx+n-1) 11 | local when, fun = pair[1], pair[2] 12 | if 'function' == type(when) then 13 | return when() 14 | elseif target == when then 15 | return fun() 16 | end 17 | end 18 | end 19 | 20 | function match_case(target, ...) 21 | local rest = {...} 22 | local n = 2 23 | for idx=1, #rest, n do 24 | local pair = Table.slice(rest, idx, idx+n-1) 25 | local when, fun = pair[1], pair[2] 26 | if 'function' == type(when) then 27 | return when() 28 | elseif target then 29 | local one, two = string.find(target, when) 30 | if two and two > 0 then 31 | return fun() 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /luacat/DateExt.lua: -------------------------------------------------------------------------------- 1 | require 'NumberExt' 2 | 3 | local ONE_DAY_SECONDS = 86400 4 | local ONE_HOUR_SECONDS = 3600 5 | local ONE_MINUTE_SECONDS = 60 6 | local ONE_DAY_HOURS = 24 7 | 8 | Date = extends(Object) 9 | 10 | local function _new_date(time) 11 | local date = os.date("*t", time) 12 | date.time = time 13 | return new_object(date, Date.mt, 'date') 14 | end 15 | 16 | -- instance methods 17 | function Date.getYesterday(self) 18 | return _new_date(self.time - ONE_DAY_SECONDS) 19 | end 20 | 21 | function Date.getTomorrow(self) 22 | return _new_date(self.time + ONE_DAY_SECONDS) 23 | end 24 | 25 | function Date.before(self, time_interval) 26 | return _new_date(self.time - time_interval) 27 | end 28 | 29 | function Date.after(self, time_interval) 30 | return _new_date(self.time + time_interval) 31 | end 32 | 33 | -- time interval 34 | function time_interval_to_days(time_interval) 35 | local seconds = time_interval 36 | local days, hours, minutes = 0 37 | if seconds >= ONE_DAY_SECONDS then 38 | days = math.floor(seconds / ONE_DAY_SECONDS) 39 | seconds = seconds - days * ONE_DAY_SECONDS 40 | if seconds >= ONE_HOUR_SECONDS then 41 | hours = math.floor(seconds / ONE_HOUR_SECONDS) 42 | seconds = seconds - hours * ONE_HOUR_SECONDS 43 | if seconds >= ONE_MINUTE_SECONDS then 44 | minutes = math.floor(seconds / ONE_MINUTE_SECONDS) 45 | seconds = seconds - minutes * ONE_MINUTE_SECONDS 46 | end 47 | end 48 | end 49 | return { days = days, hours = hours, minutes = minutes, seconds = seconds } 50 | end 51 | 52 | function Number.getDays(self) 53 | return self * ONE_DAY_SECONDS 54 | end 55 | 56 | function Number.getHours(self) 57 | return self * ONE_HOUR_SECONDS 58 | end 59 | 60 | function Number.getMinutes(self) 61 | return self * ONE_MINUTE_SECONDS 62 | end 63 | 64 | function Number.getSeconds(self) 65 | return self 66 | end 67 | 68 | 69 | 70 | 71 | -- class methods 72 | function Date.new(year, month, day) 73 | return _new_date(os.time({year=year,month=month,day=day,hour=0,min=0,sec=0})) 74 | end 75 | 76 | function Date.today() 77 | return _new_date(os.time()) 78 | end 79 | 80 | Date.mt.__lt = function(a, b) 81 | return a.time < b.time 82 | end 83 | 84 | Date.mt.__sub = function(a, b) 85 | return a.time - b.time 86 | end 87 | 88 | 89 | INFINITY = 0 90 | 91 | Time = extends(Object) 92 | function Time.milliseconds(n) 93 | return n 94 | end 95 | function Time.seconds(n) 96 | return 1000 * n 97 | end 98 | -------------------------------------------------------------------------------- /luacat/Exception.lua: -------------------------------------------------------------------------------- 1 | -- Exception.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | function try(fun, catchFun) 6 | local status, exception = pcall(fun) 7 | if not status and nil ~= catchFun then 8 | return catchFun(exception) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /luacat/File.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | File = extends(Object) 4 | 5 | File.initialize = function(self, opened_file) 6 | self.opened_file = opened_file 7 | end 8 | 9 | function File.open(name) 10 | local path = name 11 | local file = File.new(io.open(path, 'r')) 12 | return file 13 | end 14 | 15 | function File.read(self) 16 | return self.opened_file:read('*all') 17 | end 18 | 19 | function File.readlines(self) 20 | return String.split(self.read(), LF) 21 | end 22 | 23 | function File.close(self) 24 | io.close(self.opened_file) 25 | end 26 | -------------------------------------------------------------------------------- /luacat/Hangul.lua: -------------------------------------------------------------------------------- 1 | -- Hangul.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | 6 | EMPTY = "" 7 | Hangul = { 8 | Chosungs = _w"ㄱ ㄲ ㄴ ㄷ ㄸ ㄹ ㅁ ㅂ ㅃ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ", 9 | Jungsungs = _w"ㅏ ㅐ ㅑ ㅒ ㅓ ㅔ ㅕ ㅖ ㅗ ㅘ ㅙ ㅚ ㅛ ㅜ ㅝ ㅞ ㅟ ㅠ ㅡ ㅢ ㅣ", 10 | Jongsungs = Table.concat({EMPTY}, _w"ㄱ ㄲ ㄳ ㄴ ㄵ ㄶ ㄷ ㄹ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅁ ㅂ ㅄ ㅅ ㅆ ㅇ ㅈ ㅊ ㅋ ㅌ ㅍ ㅎ"), 11 | ChosungOffset = 21 * 28, 12 | JungsungOffset = 28, 13 | Ga = 0xAC00, 14 | Hih = 0xD7A3, 15 | } 16 | 17 | function string_to_uchars(str) 18 | local uchars = {} 19 | local three = {} 20 | for k,v in pairs({str:byte(1, #str)}) do 21 | if v <= 127 then 22 | table.insert(uchars, string.char(v)) 23 | else 24 | table.insert(three, v) 25 | if 3 == #three then 26 | table.insert(uchars, string.char(unpack(three))) 27 | three = {} 28 | end 29 | end 30 | end 31 | return uchars 32 | end 33 | 34 | function uchars_to_string(uchars) 35 | return Table.join(uchars, '') 36 | end 37 | 38 | function hangul_chosungs(str) 39 | local ary = {} 40 | for k,v in pairs(string_to_uchars(str)) do 41 | local t = hangul_split(v) 42 | table.insert(ary, t[1]) 43 | end 44 | return ary 45 | end 46 | 47 | function group_by_chosung(words) 48 | local group = {} 49 | for k,word in pairs(words) do 50 | for k,v in pairs(string_to_uchars(word)) do 51 | local t = hangul_split(v) 52 | local chosung = t[1] 53 | if nil == group[chosung] then 54 | group[chosung] = {word} 55 | else 56 | table.insert(group[chosung], word) 57 | end 58 | break 59 | end 60 | end 61 | return group 62 | end 63 | 64 | function hangul_split(uchar) 65 | local n = string_to_utf8_char(uchar) 66 | if n >= Hangul.Ga and n <= Hangul.Hih then 67 | n = n - Hangul.Ga 68 | local n1 = float_to_int(n / Hangul.ChosungOffset) + 1 69 | n = n % Hangul.ChosungOffset 70 | local n2 = float_to_int(n / Hangul.JungsungOffset) + 1 71 | local n3 = float_to_int(n % Hangul.JungsungOffset) + 1 72 | return { Hangul.Chosungs[n1], 73 | Hangul.Jungsungs[n2], 74 | Hangul.Jongsungs[n3] } 75 | else 76 | return { uchar } 77 | end 78 | end 79 | 80 | function hangul_join(ary) 81 | local cho, jung, jong = ary[1], ary[2], ary[3] 82 | local uch = Hangul.Ga + 83 | (Table.index(Hangul.Chosungs, cho) - 1) * Hangul.ChosungOffset + 84 | (Table.index(Hangul.Jungsungs, jung) - 1) * Hangul.JungsungOffset + 85 | (Table.index(Hangul.Jongsungs, jong) - 1) 86 | return utf8_char_to_string(uch) 87 | end 88 | 89 | function hangul_string_split(str) 90 | local result = {} 91 | for k,v in pairs(string_to_uchars(str)) do 92 | table.insert(result, hangul_split(v)) 93 | end 94 | return result 95 | end 96 | 97 | local function _hangul_string_split_out(str) 98 | local result = {} 99 | for k,v in pairs(string_to_uchars(str)) do 100 | table.insert(result, Table.join(hangul_split(v), EMPTY)) 101 | end 102 | return Table.join(result, EMPTY) 103 | end 104 | 105 | function hangul_search(words, part) 106 | local target = _hangul_string_split_out(part) 107 | local result = {} 108 | for k,word in pairs(words) do 109 | local t = _hangul_string_split_out(word) 110 | if String.include(t, target) then 111 | table.insert(result, word) 112 | end 113 | end 114 | return result 115 | end 116 | 117 | 118 | 119 | -- part of http://luaparse.luaforge.net/libquery.lua.html 120 | local function X(str) return tonumber(str, 16) end 121 | local lastUtf8 = X"10FFFF" 122 | local firstSurrogate = X"D800" 123 | local lastSurrogate = X"DFFF" 124 | local elevenBits = X"7FF" 125 | local sixteenBits = X"FFFF" 126 | local offset2 = X"C0" * 64 + X"80" 127 | local offset3 = X"E0" * 4096 + X"80" * (64 + 1) 128 | local offset4 = X"F0" * 262144 + X"80" * (4096 + 64 + 1) 129 | 130 | function string_to_utf8_char(str) 131 | if str:find("^[\1-\127%z]$") then return str:byte() 132 | elseif str:find("^[\194-\223][\128-\191]$") then 133 | return str:byte(1) * 64 + str:byte(2) - offset2 134 | elseif str:find("^[\225-\236\238\239][\128-\191][\128-\191]$") 135 | or str:find("^\224[\160-\191][\128-\191]$") 136 | or str:find("^\237[\128-\159][\128-\191]$") then 137 | return str:byte(1) * 4096 + str:byte(2) * 64 + str:byte(3) 138 | - offset3 139 | elseif str:find("^\240[\144-\191][\128-\191][\128-\191]$") 140 | or str:find("^[\241\242\243][\128-\191][\128-\191][\128-\191]$") 141 | or str:find("^\244[\128-\143][\128-\191][\128-\191]$") then 142 | return (str:byte(1) * 262144 - offset4) 143 | + str:byte(2) * 4096 + str:byte(3) * 64 + str:byte(4) 144 | end 145 | end 146 | _u = string_to_utf8_char 147 | 148 | function utf8_char_to_string(i) 149 | local strchar = string.char 150 | local mod = math.mod 151 | if i <= 127 then return strchar(i) 152 | elseif i <= elevenBits then 153 | return strchar(i / 64 + 192, mod(i, 64) + 128) 154 | elseif i <= sixteenBits then 155 | return strchar(i / 4096 + 224, 156 | mod(i / 64, 64) + 128, 157 | mod(i, 64) + 128) 158 | else 159 | return strchar(i / 262144 + 240, 160 | mod(i / 4096, 64) + 128, 161 | mod(i / 64, 64) + 128, 162 | mod(i, 64) + 128) 163 | end 164 | end 165 | -------------------------------------------------------------------------------- /luacat/Logger.lua: -------------------------------------------------------------------------------- 1 | -- Logger.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | inspect = require 'inspect' 6 | require 'ObjectExt' 7 | require 'TableExt' 8 | require 'Exception' 9 | require 'StringExt' 10 | 11 | if nil == Logger then 12 | Logger = { 13 | log_info = nil, 14 | log_write = nil, 15 | } 16 | end 17 | 18 | local function _extract_filename_line_for_log_info(traceback) 19 | local PLAIN = true 20 | local tailcall = string.find(traceback, '(tail call): ?', 1, PLAIN) 21 | local text = nil 22 | local index = -1 23 | if nil == tailcall then 24 | if string.find(traceback, 'UnitTest.lua', 1, PLAIN) then 25 | index = -3 26 | end 27 | text = traceback 28 | else 29 | local from = 1 30 | local moai = string.find(traceback, 'MoaiInfo.lua', 1, PLAIN) 31 | if moai then 32 | from = moai 33 | index = 2 34 | end 35 | text = String.slice(traceback, from, tailcall) 36 | end 37 | --print('index', index, text) 38 | return _(_(_(_(_(text). 39 | split(": in function '")).at(index)). 40 | split(': ')[1]).split(LF)[2]).lstrip() 41 | end 42 | 43 | local function print_line(line) 44 | print(string.format("%-23s %s", 45 | _extract_filename_line_for_log_info(debug.traceback()), line)) 46 | end 47 | 48 | function log_info_impl(one, ...) 49 | local fun = function(x) 50 | if "string" == type(x) then 51 | return x 52 | else 53 | return inspect(x) 54 | end 55 | end 56 | local rest = {...} 57 | if 0 == #rest then 58 | print_line(fun(one)) 59 | else 60 | try(function() 61 | if 'string' == type(one) and String.include(one, PERCENT) then 62 | print_line(string.format(one, unpack(Table.map(rest, fun)))) 63 | else 64 | format = Table.join(Table.new(1 + #rest, '%s'), SPACE) 65 | print_line(string.format(format, fun(one), unpack(Table.map(rest, fun)))) 66 | end 67 | end, 68 | function(exception) print_line(exception, one, inspect(rest)) end) 69 | end 70 | end 71 | 72 | function log_write_impl(one, ...) 73 | io.write(one, ...) 74 | io.flush() 75 | end 76 | 77 | function log_info(one, ...) 78 | if nil == Logger.log_info then 79 | log_info_impl(one, ...) 80 | else 81 | Logger.log_info(one, ...) 82 | end 83 | end 84 | 85 | function log_write(one, ...) 86 | if nil == Logger.log_write then 87 | log_write_impl(one, ...) 88 | else 89 | Logger.log_write(one, ...) 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /luacat/NumberExt.lua: -------------------------------------------------------------------------------- 1 | -- NumberExt.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'Exception' 6 | 7 | PI = math.pi 8 | FF = 255 9 | 10 | 11 | function is_odd(num) 12 | return 1 == num % 2 13 | end 14 | 15 | function int_to_char(num) 16 | return string.char(num) 17 | end 18 | 19 | function char_to_int(char) 20 | return string.byte(char) 21 | end 22 | 23 | function string_to_int(str) 24 | return tonumber(str) 25 | end 26 | 27 | function string_to_float(str) 28 | if String.count(str, DOT) > 1 then 29 | return tonumber(string.match(str, "%d.%d")) 30 | else 31 | return tonumber(str) 32 | end 33 | end 34 | 35 | function float_to_int(num) 36 | return math.floor(num) 37 | end 38 | 39 | function Number.is_odd(self) 40 | return is_odd(self) 41 | end 42 | 43 | function Number.chr(self) 44 | return int_to_char(self) 45 | end 46 | 47 | function Number.times(self, fun) 48 | for idx=1, self do 49 | fun(idx) 50 | end 51 | return self 52 | end 53 | 54 | function Number.upto(self, to, fun) 55 | for idx=self, to do 56 | fun(idx) 57 | end 58 | return self 59 | end 60 | 61 | function Number.downto(self, to, fun) 62 | for idx=self, to, -1 do 63 | fun(idx) 64 | end 65 | return self 66 | end 67 | 68 | 69 | 70 | local _socket = nil 71 | try(function() _socket = require 'socket' end, function() end) 72 | if nil == socket then 73 | try(function() 74 | require 'luarocks.loader' 75 | _socket = require 'socket' 76 | end, function() 77 | _socket = { gettime = function() return os.time() end } 78 | end) 79 | end 80 | local _old_time_seed = nil 81 | local _last_random = math.random(0,1000000000) 82 | function get_random(num) 83 | while true do 84 | local new_time_seed = _socket.gettime() * 10000 + _last_random 85 | if _old_time_seed == new_time_seed then 86 | else 87 | _old_time_seed = new_time_seed 88 | math.randomseed(new_time_seed) 89 | _last_random = math.random(0,1000000000) 90 | local random = math.random(0,num) 91 | --print('seed: ', new_time_seed, 'random :', random) 92 | return random 93 | end 94 | end 95 | return math.random(0,num) 96 | end 97 | -------------------------------------------------------------------------------- /luacat/ObjectExt.lua: -------------------------------------------------------------------------------- 1 | -- ObjectExt.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | local inspect = require 'inspect' 6 | 7 | 8 | local function _find_method_by_name(name, klass, superclass) 9 | local method = klass[name] 10 | if nil == method then 11 | local super = superclass 12 | while nil ~= super do 13 | for k,v in pairs(super) do 14 | if k == name then 15 | return v 16 | end 17 | end 18 | super = super.superclass 19 | end 20 | else 21 | return method 22 | end 23 | return nil 24 | end 25 | 26 | function extends(superclass) 27 | local klass = { __type = 'class' } 28 | klass.superclass = superclass 29 | klass.mt = { 30 | __newindex = function(self, name, ...) 31 | local setterName = 'set' .. String.capitalize(name) 32 | local setter = _find_method_by_name(setterName, klass, superclass) 33 | if nil == setter then 34 | self.__value[name] = ... 35 | else 36 | if is_base_type(self.__type) then 37 | setter(self.__value, ...) 38 | else 39 | setter(self, ...) 40 | end 41 | end 42 | return nil 43 | end, 44 | 45 | __index = function(self, name) 46 | if 'class' == name then 47 | return klass 48 | elseif "nil" ~= self.__type and 'table' == type(self.__value) then 49 | for k,v in pairs(self.__value) do 50 | if k == name then 51 | return v 52 | end 53 | end 54 | end 55 | 56 | local getterName = 'get' .. String.capitalize(name) 57 | local getter = _find_method_by_name(getterName, klass, superclass) 58 | if nil == getter then 59 | local method = _find_method_by_name(name, klass, superclass) 60 | if nil ~= method then 61 | if is_base_type(self.__type) then 62 | return function(...) return method(self.__value, ...) end 63 | else 64 | return function(...) return method(self, ...) end 65 | end 66 | end 67 | else 68 | if is_base_type(self.__type) then 69 | return getter(self.__value) 70 | else 71 | return getter(self) 72 | end 73 | end 74 | return nil 75 | end, 76 | } 77 | klass.new = function(...) 78 | local initialize = _find_method_by_name('initialize', klass, superclass) 79 | local obj = {} 80 | local instance = new_object(obj, klass.mt, 'object') 81 | if 'function' == type(initialize) then 82 | initialize(instance, ...) 83 | end 84 | return instance 85 | end 86 | klass.import = function(dict, fun) 87 | local func = fun or function(k,v) return v end 88 | for k,v in pairs(dict) do 89 | klass[k] = func(k,v) 90 | end 91 | end 92 | klass.synthesize = function(list, fun) 93 | for _,name in pairs(list) do 94 | local getterName = 'get' .. String.capitalize(name) 95 | local setterName = 'set' .. String.capitalize(name) 96 | klass[getterName] = function(self) 97 | return fun(self)[name] 98 | end 99 | klass[setterName] = function(self, val) 100 | fun(self)[name] = val 101 | end 102 | end 103 | end 104 | klass.wrap_synthesize = function(list) 105 | for _,name in pairs(list) do 106 | local getterName = 'get' .. String.capitalize(name) 107 | local setterName = 'set' .. String.capitalize(name) 108 | klass[getterName] = function(self) 109 | local val = { self.wrap[getterName](self.wrap) } 110 | if 0 == #val then 111 | return nil 112 | elseif 1 == #val then 113 | return val[1] 114 | else 115 | return val 116 | end 117 | end 118 | klass[setterName] = function(self, val) 119 | local fun = self.wrap[setterName] 120 | if 'table' == type(val) then 121 | fun(self.wrap, unpack(val)) 122 | else 123 | fun(self.wrap, val) 124 | end 125 | end 126 | end 127 | end 128 | klass.is_a = function(self, target) 129 | if klass == target then 130 | return true 131 | else 132 | local super = superclass 133 | while nil ~= super do 134 | if super == target then 135 | return true 136 | end 137 | super = super.superclass 138 | end 139 | return false 140 | end 141 | end 142 | return klass 143 | end 144 | 145 | function is_base_type(t) 146 | local baseMap = { 147 | boolean = true, 148 | number = true, 149 | string = true, 150 | table = true, 151 | } 152 | baseMap['nil'] = true 153 | baseMap['function'] = true 154 | return baseMap[t] 155 | end 156 | 157 | 158 | Object = { mt = {} } 159 | Number = extends(Object) 160 | String = extends(Object) 161 | Table = extends(Object) 162 | Nil = extends(Object) 163 | Boolean = extends(Object) 164 | Function = extends(Object) 165 | 166 | 167 | function new_object(value, mt, objType) 168 | local valueTable = { __type = objType, __value = value} 169 | setmetatable(valueTable, mt) 170 | return valueTable 171 | end 172 | 173 | function _(obj) 174 | local mtMap = { 175 | boolean = Boolean.mt, 176 | number = Number.mt, 177 | string = String.mt, 178 | table = Table.mt, 179 | } 180 | mtMap['nil'] = Nil.mt 181 | mtMap['function'] = Function.mt 182 | local objType = type(obj) 183 | local mt = mtMap[objType] 184 | return new_object(obj, mt, objType) 185 | end 186 | 187 | function is_nil(obj) 188 | return nil == obj 189 | end 190 | 191 | function is_not_nil(obj) 192 | return nil ~= obj 193 | end 194 | 195 | function Object.mixin(t) 196 | local klass = extends(Object) 197 | for k,v in pairs(t) do 198 | klass[k] = v 199 | end 200 | return klass 201 | end 202 | 203 | function Object.is_nil(self) 204 | return is_nil(self) 205 | end 206 | 207 | function Object.is_not_nil(self) 208 | return is_not_nil(self) 209 | end 210 | 211 | function Object.methods(self) 212 | local ary = {} 213 | local klass = nil 214 | if 'table' == type(self) and nil ~= self.__type then 215 | if 'class' == self.__type then 216 | klass = self 217 | else 218 | klass = self.class 219 | end 220 | else 221 | klass = _(self).class 222 | end 223 | for k,v in pairs(klass) do 224 | if "function" == type(v) then 225 | table.insert(ary, k) 226 | end 227 | end 228 | return ary 229 | end 230 | 231 | function Object.method(self, method) 232 | return self[method] 233 | end 234 | -------------------------------------------------------------------------------- /luacat/StringExt.lua: -------------------------------------------------------------------------------- 1 | -- StringExt.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'ObjectExt' 5 | require 'TableExt' 6 | local inspect = require 'inspect' 7 | 8 | LF = "\n" 9 | DOT = "." 10 | SPACE = " " 11 | SLASH = "/" 12 | PERCENT = "%" 13 | COMMA = "," 14 | COMMA_SPACE = ", " 15 | 16 | 17 | function SWF(format, ...) 18 | return string.format(format, ...) 19 | end 20 | 21 | function _w(str) 22 | return String.split(str, SPACE) 23 | end 24 | 25 | function to_s(one, ...) 26 | local rest = {...} 27 | if 0 == #rest then 28 | return inspect(one) 29 | else 30 | return Table.join( 31 | Table.map(Table.concat({one}, rest), 32 | function(obj) return inspect(obj) end), 33 | COMMA_SPACE) 34 | end 35 | end 36 | 37 | 38 | -------------------- 39 | -- String Extensions 40 | -------------------- 41 | 42 | function String.is_empty(self) 43 | return 0 == #self 44 | end 45 | 46 | function String.slice(self, from, to) 47 | return string.sub(self, from, to) 48 | end 49 | 50 | function String.length(self) 51 | return string.len(self) 52 | end 53 | 54 | function String.reverse(self) 55 | return string.reverse(self) 56 | end 57 | 58 | function String.upcase(self) 59 | return string.upper(self) 60 | end 61 | 62 | function String.downcase(self) 63 | return string.lower(self) 64 | end 65 | 66 | function String.capitalize(self) 67 | if #self > 0 then 68 | return string.upper(string.sub(self, 1, 1)) .. string.sub(self, 2, -1) 69 | else 70 | return '' 71 | end 72 | end 73 | 74 | local PLAIN = true 75 | local PATTERN = false 76 | function String.start_with(self, prefix) 77 | return string.find(self, prefix, 1, PLAIN) == 1 78 | end 79 | 80 | function String.end_with(self, suffix) 81 | local idx = #self - #suffix + 1 82 | return string.find(self, suffix, idx, PLAIN) == idx 83 | end 84 | 85 | function String.include(self, substr) 86 | return nil ~= string.find(self, substr, 1, PLAIN) 87 | end 88 | 89 | function String.split(self, pat) 90 | local t = {} -- NOTE: use {n = 0} in Lua-5.0 91 | local fpat = "(.-)" .. pat 92 | local last_end = 1 93 | local s, e, cap = string.find(self, fpat, 1, PATTERN) 94 | while s do 95 | if s ~= 1 or cap ~= "" then 96 | table.insert(t,cap) 97 | end 98 | last_end = e+1 99 | s, e, cap = string.find(self, fpat, last_end, PATTERN) 100 | end 101 | if last_end <= #self then 102 | cap = string.sub(self, last_end) 103 | table.insert(t, cap) 104 | end 105 | return t 106 | end 107 | 108 | -- http://penlight.luaforge.net/ 109 | local function _find_all(s,sub,first,last) 110 | local i1,i2 = string.find(s, sub, first, PLAIN) 111 | local res = 0 112 | local k = 0 113 | while i1 do 114 | res = i1 115 | k = k + 1 116 | i1,i2 = string.find(s,sub,i2+1,PLAIN) 117 | if last and i1 > last then 118 | break 119 | end 120 | end 121 | return res,k 122 | end 123 | 124 | local function _strip(str, stripLeft, stripRight) 125 | if stripLeft then 126 | local i1,i2 = string.find(str, '^%s*') 127 | if i2 >= i1 then 128 | str = string.sub(str, i2+1) 129 | end 130 | end 131 | if stripRight then 132 | local i1,i2 = string.find(str, '%s*$') 133 | if i2 >= i1 then 134 | str = string.sub(str, 1, i1-1) 135 | end 136 | end 137 | return str 138 | end 139 | 140 | function String.count(self, substr) 141 | local _,cnt = _find_all(self, substr, 1) 142 | return cnt 143 | end 144 | 145 | function String.strip(self) 146 | return _strip(self, true, true) 147 | end 148 | 149 | function String.lstrip(self) 150 | return _strip(self, true, false) 151 | end 152 | 153 | function String.rstrip(self) 154 | return _strip(self, false, true) 155 | end 156 | 157 | function String.gsub(self, from, to) 158 | return string.gsub(self, from, to) 159 | end 160 | 161 | function String.concat(self, other) 162 | return self .. other 163 | end 164 | 165 | String.mt.__mul = function(self, n) 166 | return string.rep(self.__value, n) 167 | end 168 | -------------------------------------------------------------------------------- /luacat/TableExt.lua: -------------------------------------------------------------------------------- 1 | -- TableExt.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'ObjectExt' 5 | require 'NumberExt' 6 | 7 | 8 | ------------------- 9 | -- Array Extensions 10 | ------------------- 11 | 12 | function Table.new(size, obj) 13 | local ary = {} 14 | for idx = 1, size or 0 do 15 | table.insert(ary, obj) 16 | end 17 | return ary 18 | end 19 | 20 | function Table.join(self, sep) 21 | return table.concat(self, sep) 22 | end 23 | 24 | function Table.concat(self, other) 25 | local ary = self 26 | for k,v in pairs(other) do 27 | table.insert(ary, v) 28 | end 29 | return ary 30 | end 31 | 32 | function Table.push(self, e, ...) 33 | table.insert(self, e) 34 | for _,v in pairs({...}) do 35 | table.insert(self, v) 36 | end 37 | return self 38 | end 39 | 40 | function Table.pop(self, n) 41 | local count = #self 42 | if 0 == count then 43 | return nil 44 | else 45 | if nil == n then 46 | local e = self[count] 47 | table.remove(self, count) 48 | return e 49 | else 50 | local e = Table.slice(self, count-n+1, count) 51 | for idx = 1, n do 52 | table.remove(self, count - idx + 1) 53 | end 54 | return e 55 | end 56 | end 57 | end 58 | 59 | 60 | function Table.reverse(self) 61 | local ary = {} 62 | for idx = #self, 1, -1 do 63 | table.insert(ary, self[idx]) 64 | end 65 | return ary 66 | end 67 | 68 | function Table.index(self, obj) 69 | for idx,e in ipairs(self) do 70 | if e == obj then 71 | return idx 72 | end 73 | end 74 | return nil 75 | end 76 | 77 | -- http://penlight.luaforge.net/ 78 | function Table.slice(self, first, last) 79 | if 'table' == type(first) then 80 | last = first[2] 81 | first = first[1] 82 | end 83 | local sz = #self 84 | --if not first then first=1 end 85 | if first < 0 then first=sz+first+1 end 86 | if not last then last=sz end 87 | if last < 0 then last=sz+1+last end 88 | local res={} 89 | for i = first, last do 90 | table.insert(res, self[i]) 91 | end 92 | return res 93 | end 94 | 95 | function Table.at(self, idx) 96 | if idx > 0 then 97 | return self[idx] 98 | else 99 | return Table.slice(self, idx, idx)[1] 100 | end 101 | end 102 | 103 | function Table.map_with_index(self, fun) 104 | local ary = {} 105 | for idx,e in ipairs(self) do 106 | table.insert(ary, fun(e, idx)) 107 | end 108 | return ary 109 | end 110 | 111 | function Table.reduce(self, init, fun) 112 | local result = init 113 | for _,e in pairs(self) do 114 | result = fun(result, e) 115 | end 116 | return result 117 | end 118 | 119 | function Table.sort(self, ...) 120 | local ary = Table.to_a(self) 121 | table.sort(ary, ...) 122 | return ary 123 | end 124 | 125 | function Table.include(self, element) 126 | for _,e in pairs(self) do 127 | if e == element then 128 | return true 129 | end 130 | end 131 | return false 132 | end 133 | 134 | function Table.flatten(self) 135 | local ary = {} 136 | for _,e in pairs(self) do 137 | if 'table' == type(e) then 138 | local flatted = Table.flatten(e) 139 | for _,v in pairs(flatted) do 140 | table.insert(ary, v) 141 | end 142 | else 143 | table.insert(ary, e) 144 | end 145 | end 146 | return ary 147 | end 148 | 149 | function Table.shuffle(self) 150 | local ary = Table.to_a(self) 151 | try(function() 152 | table.sort(ary, function(a, b) 153 | local random = get_random(2) 154 | return 1 < random 155 | end) 156 | end, function(e) 157 | end) 158 | if (#self == #ary) then 159 | return ary 160 | else 161 | return Table.shuffle(self) 162 | end 163 | end 164 | 165 | function Table.first(self) 166 | return self[1] 167 | end 168 | 169 | function Table.last(self) 170 | return self[#self] 171 | end 172 | 173 | function Table.each_slice(self, n, fun) 174 | for idx=1, #self, n do 175 | fun(Table.slice(self, idx, idx+n-1)) 176 | end 177 | end 178 | 179 | function Table.each_cons(self, n, fun) 180 | for idx=1, #self-n+1 do 181 | fun(Table.slice(self, idx, idx+n-1)) 182 | end 183 | end 184 | 185 | function Table.inject(self, result, fun) 186 | for k,e in pairs(self) do 187 | result = fun(result, e) 188 | end 189 | return result 190 | end 191 | 192 | function Table.delete_at(self, idx) 193 | local e = self[idx] 194 | table.remove(self, idx) 195 | return e 196 | end 197 | 198 | Table.mt.__mul = function(self, n) 199 | local ary = {} 200 | for idx = 1, n do 201 | Table.concat(ary, self.__value) 202 | end 203 | return ary 204 | end 205 | 206 | 207 | ------------------------ 208 | -- Dictionary Extensions 209 | ------------------------ 210 | 211 | function Table.keys(self) 212 | local keys = {} 213 | for key, _ in pairs(self) do 214 | table.insert(keys, key) 215 | end 216 | return keys 217 | end 218 | 219 | function Table.sorted_keys(self) 220 | return Table.sort(Table.keys(self)) 221 | end 222 | 223 | function Table.values(self) 224 | local values = {} 225 | for _, value in pairs(self) do 226 | table.insert(values, value) 227 | end 228 | return values 229 | end 230 | 231 | function Table.merge(self, kv) 232 | local dict = {} 233 | for k,v in pairs(self) do 234 | dict[k] = v 235 | end 236 | for k,v in pairs(kv) do 237 | dict[k] = v 238 | end 239 | return dict 240 | end 241 | 242 | function Table.update(self, kv) 243 | for k,v in pairs(kv) do 244 | self[k] = v 245 | end 246 | end 247 | 248 | function Table.append(self, k, v) 249 | local t = self[k] 250 | if nil == t then 251 | self[k] = { v } 252 | else 253 | table.insert(t, v) 254 | self[k] = t 255 | end 256 | end 257 | 258 | function Table.has_key(self, key) 259 | for k,v in pairs(self) do 260 | if k == key then 261 | return true 262 | end 263 | end 264 | return false 265 | end 266 | 267 | function Table.assoc(self, key) 268 | for k,v in pairs(self) do 269 | if k == key then 270 | return {k,v} 271 | end 272 | end 273 | return nil 274 | end 275 | 276 | function Table.rassoc(self, value) 277 | for k,v in pairs(self) do 278 | print(k) 279 | if v == value then 280 | return {k,v} 281 | end 282 | end 283 | return nil 284 | end 285 | 286 | 287 | ------------------------ 288 | -- Table Extensions 289 | ------------------------ 290 | function Table.is_empty(self) 291 | return 0 == Table.count(self) 292 | end 293 | 294 | function Table.count(self, e) 295 | if nil == e then 296 | return #Table.keys(self) 297 | else 298 | local cnt = 0 299 | for k,v in pairs(self) do 300 | if v == e then 301 | cnt = cnt + 1 302 | end 303 | end 304 | return cnt 305 | end 306 | end 307 | 308 | function Table.to_a(self) 309 | local ary = {} 310 | for k,v in pairs(self) do 311 | if "string" == type(k) then 312 | ary[#ary + 1] = {k,v} 313 | else 314 | ary[#ary + 1] = v 315 | end 316 | end 317 | return ary 318 | end 319 | 320 | function Table.equal(a, b) 321 | return inspect(a) == inspect(b) 322 | end 323 | 324 | function Table.each(self, fun) 325 | for k,e in pairs(self) do 326 | if "number" == type(k) then fun(e) else fun({k,e}) end 327 | end 328 | end 329 | 330 | function Table.each_with_index(self, fun) 331 | local idx = 1 332 | for k,e in pairs(self) do 333 | if "number" == type(k) then fun(e,idx) else fun({k,e},idx) end 334 | idx = idx + 1 335 | end 336 | end 337 | 338 | function Table.map(self, fun) 339 | local ary = {} 340 | for k,e in pairs(self) do 341 | if "number" == type(k) then 342 | table.insert(ary, fun(e)) 343 | else 344 | table.insert(ary, fun(k,e)) 345 | end 346 | end 347 | return ary 348 | end 349 | 350 | function Table.select(self, fun) 351 | local ary = {} 352 | for k,e in pairs(self) do 353 | if "number" == type(k) then 354 | if fun(e) then 355 | table.insert(ary, e) 356 | end 357 | else 358 | if fun(k,e) then 359 | table.insert(ary, {k,e}) 360 | end 361 | end 362 | end 363 | return ary 364 | end 365 | 366 | function Table.reject(self, fun) 367 | local ary = {} 368 | for k,e in pairs(self) do 369 | if "number" == type(k) then 370 | if not fun(e) then 371 | table.insert(ary, e) 372 | end 373 | else 374 | if not fun(k,e) then 375 | table.insert(ary, {k,e}) 376 | end 377 | end 378 | end 379 | return ary 380 | end 381 | 382 | function Table.clear(self) 383 | for key, _ in pairs(self) do 384 | self[key] = nil 385 | end 386 | return self 387 | end 388 | 389 | function Hash(array) 390 | local dict = {} 391 | for _,e in pairs(array) do 392 | dict[e[1]] = e[2] 393 | end 394 | return dict 395 | end 396 | 397 | ------------------- 398 | -- Array Comparison 399 | ------------------- 400 | Table.mt.__lt = function(a, b) 401 | for idx,va in ipairs(a) do 402 | local vb = b[idx] 403 | if va == vb then 404 | else 405 | return va < vb 406 | end 407 | end 408 | return true 409 | end 410 | 411 | ----------- 412 | -- Iterator 413 | ----------- 414 | function each(t) 415 | return coroutine.wrap(function() 416 | for k,v in pairs(t) do 417 | if "number" == type(k) then 418 | coroutine.yield(v) 419 | else 420 | coroutine.yield(k,v) 421 | end 422 | end 423 | end) 424 | end 425 | 426 | function sorted_each(t) 427 | return coroutine.wrap(function() 428 | local keys = Table.keys(t) 429 | table.sort(keys, function(a,b) 430 | if 'table' == type(a) and 'table' == type(b) then 431 | setmetatable(a, Table.mt) 432 | setmetatable(b, Table.mt) 433 | local result = a < b 434 | setmetatable(a, nil) 435 | setmetatable(b, nil) 436 | return result 437 | else 438 | return a < b 439 | end 440 | end) 441 | for _,k in pairs(keys) do 442 | local v = t[k] 443 | if 'number' == type(k) then 444 | coroutine.yield(v) 445 | else 446 | coroutine.yield(k,v) 447 | end 448 | end 449 | end) 450 | end 451 | -------------------------------------------------------------------------------- /luacat/UnitTest.lua: -------------------------------------------------------------------------------- 1 | -- UnitTest.lua 2 | -- wookay.noh at gmail.com 3 | 4 | local inspect = require 'inspect' 5 | require 'Exception' 6 | require 'StringExt' 7 | require 'TableExt' 8 | require 'ObjectExt' 9 | 10 | local currentTest = nil 11 | UnitTest = { dot_if_passed = true, tests = {}, passed = 0, failed = 0, setupAt = nil } 12 | 13 | 14 | local function _extract_filename_line_from_debug_traceback(traceback) 15 | return _(_(_(_(_(traceback). 16 | split(LF)).slice(4,-2)).join("")).split(': ')[1]).lstrip() 17 | end 18 | 19 | local function _assert_equal(expected, got, expected_one, got_one) 20 | if expected == got then 21 | UnitTest.passed = UnitTest.passed + 1 22 | if nil ~= currentTest then 23 | UnitTest.tests[currentTest].passed = UnitTest.tests[currentTest].passed + 1 24 | end 25 | if UnitTest.dot_if_passed then 26 | io.write('.') 27 | else 28 | print("passed: " .. inspect(got_one)) 29 | end 30 | else 31 | UnitTest.failed = UnitTest.failed + 1 32 | if nil ~= currentTest then 33 | UnitTest.tests[currentTest].failed = UnitTest.tests[currentTest].failed + 1 34 | end 35 | if UnitTest.dot_if_passed then 36 | io.write(LF) 37 | end 38 | print(string.format("Assertion failed in %s\nExpected: %s\nGot: %s", 39 | _extract_filename_line_from_debug_traceback(debug.traceback()), 40 | inspect(expected_one), 41 | inspect(got_one))) 42 | end 43 | end 44 | 45 | function assert_equal(expected, got) 46 | if "table" == type(expected) and "table" == type(got) then 47 | _assert_equal(inspect(expected), inspect(got), expected, got) 48 | else 49 | _assert_equal(expected, got, expected, got) 50 | end 51 | end 52 | 53 | function assert_nil(got) 54 | _assert_equal(nil, got, nil, got) 55 | end 56 | 57 | function assert_not_nil(got) 58 | _assert_equal(true, nil ~= got, "not nil", got) 59 | end 60 | 61 | function assert_not_equal(expected, got) 62 | if "table" == type(expected) and "table" == type(got) then 63 | _assert_equal(true, inspect(expected) ~= inspect(got), "not equal", got) 64 | else 65 | _assert_equal(true, expected ~= got, "not equal", got) 66 | end 67 | end 68 | 69 | function assert_empty(got) 70 | if "table" == type(got) then 71 | _assert_equal(true, Table.is_empty(got), "empty", got) 72 | elseif "string" == type(got) then 73 | _assert_equal(true, String.is_empty(got), "empty", got) 74 | else 75 | error(SWF("assert_empty but %s", to_s(got))) 76 | end 77 | end 78 | 79 | function assert_not_empty(got) 80 | if "table" == type(got) then 81 | _assert_equal(false, Table.is_empty(got), "not empty", got) 82 | elseif "string" == type(got) then 83 | _assert_equal(false, String.is_empty(got), "not empty", got) 84 | else 85 | error(SWF("assert_not_empty but %s", to_s(got))) 86 | end 87 | end 88 | 89 | function assert_one_of(expected, got) 90 | _assert_equal(true, Table.include(expected, got), "one of", got) 91 | end 92 | 93 | function assert_true(got) 94 | _assert_equal(true, got, true, got) 95 | end 96 | 97 | function assert_false(got) 98 | _assert_equal(false, got, false, got) 99 | end 100 | 101 | function assert_raise(exception, fun) 102 | try(fun, 103 | function(e) _assert_equal(true, String.include(e, exception), exception, e) end) 104 | end 105 | 106 | function UnitTest.setup() 107 | UnitTest.setupAt = os.clock() 108 | print("Started") 109 | end 110 | 111 | function UnitTest.report() 112 | if Table.count(UnitTest.tests) > 0 then 113 | print(string.format("\nFinished in %.4f seconds.", os.clock() - UnitTest.setupAt)) 114 | print(string.format("%d tests, %d assertions, %d failures, %d errors", 115 | Table.count(UnitTest.tests), 116 | UnitTest.passed, 117 | UnitTest.failed, 118 | 0)) 119 | end 120 | end 121 | 122 | local TEST_PREFIX = 'test_' 123 | function UnitTest.run(test_fun) 124 | local tests = {} 125 | if 'table' == type(test_fun) then 126 | local klass = Object.mixin(test_fun) 127 | local instance = klass.new() 128 | for _,name in pairs(instance.methods()) do 129 | if String.start_with(name, TEST_PREFIX) then 130 | UnitTest.tests[name] = { 131 | test = instance[name], 132 | passed = 0, 133 | failed = 0, 134 | } 135 | currentTest = key 136 | if nil ~= instance.setup then 137 | instance.setup() 138 | end 139 | instance[name]() 140 | if nil ~= instance.teardown then 141 | instance.teardown() 142 | end 143 | currentTest = nil 144 | end 145 | end 146 | else 147 | if nil == test_fun then 148 | for name,func in pairs(getfenv()) do 149 | if String.start_with(name, TEST_PREFIX) then 150 | tests[name] = func 151 | end 152 | end 153 | else 154 | tests['test'] = test_fun 155 | end 156 | local didSetup = false 157 | for name,func in pairs(tests) do 158 | if not didSetup then 159 | didSetup = true 160 | UnitTest.setup() 161 | end 162 | UnitTest.tests[name] = { 163 | test = func, 164 | passed = 0, 165 | failed = 0, 166 | } 167 | currentTest = name 168 | func() 169 | currentTest = nil 170 | end 171 | UnitTest.report() 172 | end 173 | end 174 | 175 | 176 | function is_main() 177 | if nil == arg then 178 | return false 179 | else 180 | return arg[0] == string.sub(debug.getinfo(2,'S').source,2) 181 | end 182 | end 183 | -------------------------------------------------------------------------------- /luacat/inspect.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------------------------------------------------- 2 | -- inspect.lua - v1.1 (2011-01) 3 | -- Enrique García Cota - enrique.garcia.cota [AT] gmail [DOT] com 4 | -- human-readable representations of tables. 5 | -- inspired by http://lua-users.org/wiki/TableSerialization 6 | ----------------------------------------------------------------------------------------------------------------------- 7 | 8 | -- Apostrophizes the string if it has quotes, but not aphostrophes 9 | -- Otherwise, it returns a regular quoted string 10 | local function smartQuote(str) 11 | if string.match( string.gsub(str,"[^'\"]",""), '^"+$' ) then 12 | return "'" .. str .. "'" 13 | end 14 | return string.format("%q", str ) 15 | end 16 | 17 | local controlCharsTranslation = { 18 | ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", 19 | ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\\"] = "\\\\" 20 | } 21 | 22 | local function unescapeChar(c) return controlCharsTranslation[c] end 23 | 24 | local function unescape(str) 25 | local result, _ = string.gsub( str, "(%c)", unescapeChar ) 26 | return result 27 | end 28 | 29 | local function isIdentifier(str) 30 | return string.match( str, "^[_%a][_%a%d]*$" ) 31 | end 32 | 33 | local function isArrayKey(k, length) 34 | return type(k)=='number' and 1 <= k and k <= length 35 | end 36 | 37 | local function isDictionaryKey(k, length) 38 | return not isArrayKey(k, length) 39 | end 40 | 41 | local sortOrdersByType = { 42 | ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, 43 | ['function'] = 5, ['userdata'] = 6, ['thread'] = 7 44 | } 45 | 46 | function sortKeys(a,b) 47 | local ta, tb = type(a), type(b) 48 | if ta ~= tb then return sortOrdersByType[ta] < sortOrdersByType[tb] end 49 | if ta == 'string' or ta == 'number' then return a < b end 50 | return false 51 | end 52 | 53 | local function getDictionaryKeys(t) 54 | local length = #t 55 | local keys = {} 56 | for k,_ in pairs(t) do 57 | if isDictionaryKey(k, length) then table.insert(keys,k) end 58 | end 59 | table.sort(keys, sortKeys) 60 | return keys 61 | end 62 | 63 | local Inspector = {} 64 | 65 | function Inspector:new(v, depth) 66 | local inspector = { 67 | buffer = {}, 68 | depth = depth, 69 | level = 0, 70 | counters = { 71 | ['function'] = 0, 72 | ['userdata'] = 0, 73 | ['thread'] = 0, 74 | ['table'] = 0 75 | }, 76 | pools = { 77 | ['function'] = setmetatable({}, {__mode = "kv"}), 78 | ['userdata'] = setmetatable({}, {__mode = "kv"}), 79 | ['thread'] = setmetatable({}, {__mode = "kv"}), 80 | ['table'] = setmetatable({}, {__mode = "kv"}) 81 | } 82 | } 83 | 84 | setmetatable( inspector, { 85 | __index = Inspector, 86 | __tostring = function(instance) return table.concat(instance.buffer) end 87 | } ) 88 | return inspector:putValue(v) 89 | end 90 | 91 | function Inspector:puts(...) 92 | local args = {...} 93 | for i=1, #args do 94 | table.insert(self.buffer, tostring(args[i])) 95 | end 96 | return self 97 | end 98 | 99 | function Inspector:tabify() 100 | --self:puts("\n", string.rep(" ", self.level)) 101 | return self 102 | end 103 | 104 | function Inspector:tabify_indent() 105 | self:puts("\n", string.rep(" ", self.level)) 106 | return self 107 | end 108 | 109 | function Inspector:up() 110 | self.level = self.level - 1 111 | end 112 | 113 | function Inspector:down() 114 | self.level = self.level + 1 115 | end 116 | 117 | function Inspector:putComma(comma) 118 | if comma then self:puts(', ') end 119 | return true 120 | end 121 | 122 | function Inspector:putTable(t) 123 | if self:alreadySeen(t) then 124 | self:puts('') 125 | elseif self.level >= self.depth then 126 | self:puts('{...}') 127 | else 128 | --self:puts('<',self:getOrCreateCounter(t),'>{') 129 | 130 | local length = #t 131 | local mt = getmetatable(t) 132 | local __tostring = type(mt) == 'table' and mt.__tostring 133 | local string = type(__tostring) == 'function' and __tostring(t) 134 | 135 | if type(string) == 'string' and #string > 0 then 136 | self:puts(unescape(string)) 137 | --self:puts(' -- ', unescape(string)) 138 | if length >= 1 then self:tabify() end -- tabify the array values 139 | return self 140 | end 141 | 142 | self:puts('{') 143 | self:down() 144 | 145 | local comma = false 146 | for i=1, length do 147 | comma = self:putComma(comma) 148 | --self:puts(' '):putValue(t[i]) 149 | self:putValue(t[i]) 150 | end 151 | 152 | local dictKeys = getDictionaryKeys(t) 153 | local MULTILINE_KEY_COUNT = 10 154 | local multilined = #dictKeys > MULTILINE_KEY_COUNT 155 | if not multilined then 156 | for k,v in pairs(t) do 157 | if "table" == type(v) then 158 | multilined = true 159 | break 160 | end 161 | end 162 | end 163 | 164 | for idx,k in ipairs(dictKeys) do 165 | comma = self:putComma(comma) 166 | if multilined then 167 | if 1 == idx then 168 | self:puts(" ") 169 | else 170 | self:tabify_indent() 171 | end 172 | end 173 | self:tabify():putKey(k):puts(' = '):putValue(t[k]) 174 | end 175 | --if multilined then 176 | -- self:puts(" ") 177 | --end 178 | 179 | if mt then 180 | comma = self:putComma(comma) 181 | self:tabify():puts(' = '):putValue(mt) 182 | end 183 | self:up() 184 | 185 | if #dictKeys > 0 or mt then -- dictionary table. Justify closing } 186 | self:tabify() 187 | elseif length > 0 then -- array tables have one extra space before closing } 188 | --self:puts(' ') 189 | end 190 | self:puts('}') 191 | end 192 | return self 193 | end 194 | 195 | function Inspector:alreadySeen(v) 196 | local tv = type(v) 197 | return self.pools[tv][v] ~= nil 198 | end 199 | 200 | function Inspector:getOrCreateCounter(v) 201 | local tv = type(v) 202 | local current = self.pools[tv][v] 203 | if not current then 204 | current = self.counters[tv] + 1 205 | self.counters[tv] = current 206 | self.pools[tv][v] = current 207 | end 208 | return current 209 | end 210 | 211 | function Inspector:putValue(v) 212 | local tv = type(v) 213 | 214 | if tv == 'string' then 215 | self:puts(smartQuote(unescape(v))) 216 | elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then 217 | self:puts(tostring(v)) 218 | elseif tv == 'table' then 219 | self:putTable(v) 220 | else 221 | self:puts('<',tv,' ',self:getOrCreateCounter(v),'>') 222 | end 223 | return self 224 | end 225 | 226 | function Inspector:putKey(k) 227 | if type(k) == "string" and isIdentifier(k) then 228 | return self:puts(k) 229 | end 230 | return self:puts( "[" ):putValue(k):puts("]") 231 | end 232 | 233 | local function inspect(t, depth) 234 | depth = depth or 4 235 | return tostring(Inspector:new(t, depth)) 236 | end 237 | 238 | return inspect 239 | 240 | -------------------------------------------------------------------------------- /luacat/luacat.lua: -------------------------------------------------------------------------------- 1 | -- luacat.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'UnitTest' 5 | require 'Logger' 6 | require 'ObjectExt' 7 | require 'NumberExt' 8 | require 'StringExt' 9 | require 'TableExt' 10 | require 'DateExt' 11 | require 'Exception' 12 | require 'CaseStatement' 13 | -------------------------------------------------------------------------------- /moacat/Anim.lua: -------------------------------------------------------------------------------- 1 | -- Anim.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'MoaiNode' 6 | 7 | Anim = extends(MoaiNode) 8 | 9 | function Anim.initialize(self, prop) 10 | self.prop = prop 11 | self.wrap = MOAIAnim.new() 12 | end 13 | 14 | function Anim.setCurveWithLocations(self, locations, duration) 15 | local xCurve = MOAIAnimCurve.new() 16 | local yCurve = MOAIAnimCurve.new() 17 | local interval = 0.5 18 | if nil == duration then 19 | else 20 | interval = duration / #locations 21 | end 22 | xCurve:reserveKeys(#locations) 23 | yCurve:reserveKeys(#locations) 24 | local time = 0 25 | for idx,loc in ipairs(locations) do 26 | xCurve:setKey(idx, time, loc[1]) 27 | yCurve:setKey(idx, time, loc[2]) 28 | time = time + interval 29 | end 30 | self.wrap:reserveLinks(2) 31 | self.wrap:setLink(1, xCurve, self.prop.wrap, MOAIProp2D.ATTR_X_LOC) 32 | self.wrap:setLink(2, yCurve, self.prop.wrap, MOAIProp2D.ATTR_Y_LOC) 33 | end 34 | 35 | function Anim.start(self, loop) 36 | if loop then 37 | self.wrap:setMode(MOAITimer.LOOP) 38 | end 39 | self.wrap:start() 40 | end 41 | -------------------------------------------------------------------------------- /moacat/Button.lua: -------------------------------------------------------------------------------- 1 | -- Button.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | require 'MoaiNode' 7 | 8 | Button = extends(MoaiNode) 9 | 10 | function Button.initialize(self, callback) 11 | MoaiNode.addEndedListener(self, callback) 12 | end 13 | -------------------------------------------------------------------------------- /moacat/Color.lua: -------------------------------------------------------------------------------- 1 | -- Color.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | 7 | Color = extends(Object) 8 | 9 | function Color.initialize(self, rgba) 10 | self.rgba = rgba 11 | end 12 | 13 | function Color.getR(self) 14 | return self.rgba[1] 15 | end 16 | function Color.getG(self) 17 | return self.rgba[2] 18 | end 19 | function Color.getB(self) 20 | return self.rgba[3] 21 | end 22 | function Color.getA(self) 23 | return self.rgba[4] 24 | end 25 | function Color.setA(self, a) 26 | self.rgba[4] = a 27 | end 28 | 29 | function Color.getAlpha(self) -- 0.0 ~ 1.0 30 | return self.rgba[4] / FF 31 | end 32 | function Color.setAlpha(self, alpha) -- 0.0 ~ 1.0 33 | self.rgba[4] = alpha * FF 34 | end 35 | 36 | 37 | 38 | local color_list = { 39 | aliceblue = {240, 248, 255}, 40 | antiquewhite = {250, 235, 215}, 41 | aqua = { 0, 255, 255}, 42 | aquamarine = {127, 255, 212}, 43 | azure = {240, 255, 255}, 44 | beige = {245, 245, 220}, 45 | bisque = {255, 228, 196}, 46 | black = { 0, 0, 0}, 47 | blanchedalmond = {255, 235, 205}, 48 | blue = { 0, 0, 255}, 49 | blueviolet = {138, 43, 226}, 50 | brown = {165, 42, 42}, 51 | burlywood = {222, 184, 135}, 52 | cadetblue = { 95, 158, 160}, 53 | chartreuse = {127, 255, 0}, 54 | chocolate = {210, 105, 30}, 55 | coral = {255, 127, 80}, 56 | cornflowerblue = {100, 149, 237}, 57 | cornsilk = {255, 248, 220}, 58 | crimson = {220, 20, 60}, 59 | cyan = { 0, 255, 255}, 60 | darkblue = { 0, 0, 139}, 61 | darkcyan = { 0, 139, 139}, 62 | darkgoldenrod = {184, 134, 11}, 63 | darkgray = {169, 169, 169}, 64 | darkgreen = { 0, 100, 0}, 65 | darkgrey = {169, 169, 169}, 66 | darkkhaki = {189, 183, 107}, 67 | darkmagenta = {139, 0, 139}, 68 | darkolivegreen = { 85, 107, 47}, 69 | darkorange = {255, 140, 0}, 70 | darkorchid = {153, 50, 204}, 71 | darkred = {139, 0, 0}, 72 | darksalmon = {233, 150, 122}, 73 | darkseagreen = {143, 188, 143}, 74 | darkslateblue = { 72, 61, 139}, 75 | darkslategray = { 47, 79, 79}, 76 | darkslategrey = { 47, 79, 79}, 77 | darkturquoise = { 0, 206, 209}, 78 | darkviolet = {148, 0, 211}, 79 | deeppink = {255, 20, 147}, 80 | deepskyblue = { 0, 191, 255}, 81 | dimgray = {105, 105, 105}, 82 | dimgrey = {105, 105, 105}, 83 | dodgerblue = { 30, 144, 255}, 84 | firebrick = {178, 34, 34}, 85 | floralwhite = {255, 250, 240}, 86 | forestgreen = { 34, 139, 34}, 87 | fuchsia = {255, 0, 255}, 88 | gainsboro = {220, 220, 220}, 89 | ghostwhite = {248, 248, 255}, 90 | gold = {255, 215, 0}, 91 | goldenrod = {218, 165, 32}, 92 | gray = {128, 128, 128}, 93 | grey = {128, 128, 128}, 94 | green = { 0, 128, 0}, 95 | greenyellow = {173, 255, 47}, 96 | honeydew = {240, 255, 240}, 97 | hotpink = {255, 105, 180}, 98 | indianred = {205, 92, 92}, 99 | indigo = { 75, 0, 130}, 100 | ivory = {255, 255, 240}, 101 | khaki = {240, 230, 140}, 102 | lavender = {230, 230, 250}, 103 | lavenderblush = {255, 240, 245}, 104 | lawngreen = {124, 252, 0}, 105 | lemonchiffon = {255, 250, 205}, 106 | lightblue = {173, 216, 230}, 107 | lightcoral = {240, 128, 128}, 108 | lightcyan = {224, 255, 255}, 109 | lightgoldenrodyellow = {250, 250, 210}, 110 | lightgray = {211, 211, 211}, 111 | lightgreen = {144, 238, 144}, 112 | lightgrey = {211, 211, 211}, 113 | lightpink = {255, 182, 193}, 114 | lightsalmon = {255, 160, 122}, 115 | lightseagreen = { 32, 178, 170}, 116 | lightskyblue = {135, 206, 250}, 117 | lightslategray = {119, 136, 153}, 118 | lightslategrey = {119, 136, 153}, 119 | lightsteelblue = {176, 196, 222}, 120 | lightyellow = {255, 255, 224}, 121 | lime = { 0, 255, 0}, 122 | limegreen = { 50, 205, 50}, 123 | linen = {250, 240, 230}, 124 | magenta = {255, 0, 255}, 125 | maroon = {128, 0, 0}, 126 | mediumaquamarine = {102, 205, 170}, 127 | mediumblue = { 0, 0, 205}, 128 | mediumorchid = {186, 85, 211}, 129 | mediumpurple = {147, 112, 219}, 130 | mediumseagreen = { 60, 179, 113}, 131 | mediumslateblue = {123, 104, 238}, 132 | mediumspringgreen = { 0, 250, 154}, 133 | mediumturquoise = { 72, 209, 204}, 134 | mediumvioletred = {199, 21, 133}, 135 | midnightblue = { 25, 25, 112}, 136 | mintcream = {245, 255, 250}, 137 | mistyrose = {255, 228, 225}, 138 | moccasin = {255, 228, 181}, 139 | navajowhite = {255, 222, 173}, 140 | navy = { 0, 0, 128}, 141 | oldlace = {253, 245, 230}, 142 | olive = {128, 128, 0}, 143 | olivedrab = {107, 142, 35}, 144 | orange = {255, 165, 0}, 145 | orangered = {255, 69, 0}, 146 | orchid = {218, 112, 214}, 147 | palegoldenrod = {238, 232, 170}, 148 | palegreen = {152, 251, 152}, 149 | paleturquoise = {175, 238, 238}, 150 | palevioletred = {219, 112, 147}, 151 | papayawhip = {255, 239, 213}, 152 | peachpuff = {255, 218, 185}, 153 | peru = {205, 133, 63}, 154 | pink = {255, 192, 203}, 155 | plum = {221, 160, 221}, 156 | powderblue = {176, 224, 230}, 157 | purple = {128, 0, 128}, 158 | red = {255, 0, 0}, 159 | rosybrown = {188, 143, 143}, 160 | royalblue = { 65, 105, 225}, 161 | saddlebrown = {139, 69, 19}, 162 | salmon = {250, 128, 114}, 163 | sandybrown = {244, 164, 96}, 164 | seagreen = { 46, 139, 87}, 165 | seashell = {255, 245, 238}, 166 | sienna = {160, 82, 45}, 167 | silver = {192, 192, 192}, 168 | skyblue = {135, 206, 235}, 169 | slateblue = {106, 90, 205}, 170 | slategray = {112, 128, 144}, 171 | slategrey = {112, 128, 144}, 172 | snow = {255, 250, 250}, 173 | springgreen = { 0, 255, 127}, 174 | steelblue = { 70, 130, 180}, 175 | tan = {210, 180, 140}, 176 | teal = { 0, 128, 128}, 177 | thistle = {216, 191, 216}, 178 | tomato = {255, 99, 71}, 179 | turquoise = { 64, 224, 208}, 180 | violet = {238, 130, 238}, 181 | wheat = {245, 222, 179}, 182 | white = {255, 255, 255}, 183 | whitesmoke = {245, 245, 245}, 184 | yellow = {255, 255, 0}, 185 | yellowgreen = {154, 205, 50} 186 | } 187 | 188 | Color.import(color_list, function(k,v) 189 | return Table.map( 190 | Table.concat(v, {255}), 191 | function(x) return x/255.0 end 192 | ) 193 | end) 194 | -------------------------------------------------------------------------------- /moacat/Debug.lua: -------------------------------------------------------------------------------- 1 | -- Debug.lua 2 | -- wookay.noh at gmail.com 3 | 4 | Debug = {} 5 | Debug.HistogramEnabled = false 6 | 7 | function Debug.setLogLevelAsNone() 8 | -- LOG_NONE, LOG_ERROR, LOG_WARNING, LOG_STATUS 9 | MOAILogMgr:setLogLevel(MOAILogMgr.LOG_NONE) 10 | end 11 | 12 | function Debug.showLines() 13 | -- cyan 14 | MOAIDebugLines.setStyle(MOAIDebugLines.PARTITION_CELLS, 1, 0, 1, 1) 15 | 16 | -- blue 17 | MOAIDebugLines.setStyle(MOAIDebugLines.PARTITION_PADDED_CELLS, 1, 0, 1, 0) 18 | 19 | -- green 20 | MOAIDebugLines.setStyle(MOAIDebugLines.PROP_MODEL_BOUNDS, 1, 0, 1, 0) 21 | 22 | -- lightgray 23 | MOAIDebugLines.setStyle(MOAIDebugLines.PROP_WORLD_BOUNDS, 1, 0.83, 0.83, 0.83) 24 | 25 | -- yellow 26 | MOAIDebugLines.setStyle(MOAIDebugLines.TEXT_BOX, 1, 1, 1, 0) 27 | end 28 | 29 | function Debug.setHistogramEnabled() 30 | Debug.HistogramEnabled = true 31 | MOAISim.setHistogramEnabled(true) 32 | end 33 | -------------------------------------------------------------------------------- /moacat/Deck.lua: -------------------------------------------------------------------------------- 1 | -- Deck.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | require 'MoaiNode' 7 | require 'Image' 8 | require 'Geometry' 9 | 10 | Deck = extends(MoaiNode) 11 | 12 | function Deck.initialize(self, path, deckSize) 13 | local deckSize = deckSize or {1,1} 14 | local image = Image.new(path) 15 | local size = {image.width/deckSize[1], image.height/deckSize[2]} 16 | local mdeck = MOAITileDeck2D.new() 17 | mdeck:setSize(unpack(deckSize)) 18 | mdeck:setRect(unpack(centered_rect_by_size(size))) 19 | mdeck:setTexture(image.wrap) 20 | self.deckSize = deckSize 21 | self.size = size 22 | self.image = image 23 | self.wrap = mdeck 24 | end 25 | -------------------------------------------------------------------------------- /moacat/Device.lua: -------------------------------------------------------------------------------- 1 | -- Device.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'MoaiNode' 6 | 7 | 8 | -- DeviceManager 9 | -- Device 10 | 11 | local function new_device_event() 12 | return { 13 | lastLocation = nil, 14 | previousLocation = nil, 15 | hasPicked = false, 16 | } 17 | end 18 | 19 | local sharedDeviceManager = nil 20 | DeviceManager = extends(Object) 21 | function DeviceManager.initialize(self) 22 | self.layers = {} 23 | end 24 | function DeviceManager.updateLayer(self, layer) 25 | local found = false 26 | for k,l in pairs(self.layers) do 27 | if l.layer == layer then 28 | found = true 29 | break 30 | end 31 | end 32 | if found then 33 | else 34 | local mpartition = MOAIPartition.new() 35 | layer.wrap:setPartition(mpartition) 36 | table.insert(self.layers, { 37 | layer = layer, 38 | deviceEvent = new_device_event() 39 | }) 40 | end 41 | end 42 | 43 | Device = {} 44 | function Device.enableTouchEvents(layer) 45 | if nil == sharedDeviceManager then 46 | sharedDeviceManager = DeviceManager.new() 47 | end 48 | sharedDeviceManager.updateLayer(layer) 49 | if MOAIInputMgr.device.pointer then 50 | MOAIInputMgr.device.pointer:setCallback(device_pointer_callback) 51 | MOAIInputMgr.device.mouseLeft:setCallback(device_mouseLeft_callback) 52 | --MOAIInputMgr.device.mouseRight:setCallback(device_mouseRight_callback) 53 | --MOAIInputMgr.device.mouseMiddle:setCallback(device_mouseMiddle_callback) 54 | else 55 | MOAIInputMgr.device.touch:setCallback(device_touch_callback) 56 | end 57 | end 58 | 59 | function Device.disableTouchEvents() 60 | if MOAIInputMgr.device.pointer then 61 | MOAIInputMgr.device.pointer:setCallback(function() end) 62 | MOAIInputMgr.device.mouseLeft:setCallback(function() end) 63 | --MOAIInputMgr.device.mouseRight:setCallback(nil) 64 | --MOAIInputMgr.device.mouseMiddle:setCallback(nil) 65 | else 66 | MOAIInputMgr.device.touch:setCallback(function() end) 67 | end 68 | end 69 | 70 | function device_touch_callback(eventType, idx, x, y, tapCount) 71 | for k,l in pairs(sharedDeviceManager.layers) do 72 | local worldX, worldY = l.layer.wrap:wndToWorld(x, y) 73 | local phase = nil 74 | if MOAITouchSensor.TOUCH_DOWN == eventType then 75 | phase = Phase.began 76 | l.deviceEvent.previousLocation = {worldX,worldY} 77 | elseif MOAITouchSensor.TOUCH_MOVE == eventType then 78 | phase = Phase.moved 79 | elseif MOAITouchSensor.TOUCH_UP == eventType then 80 | phase = Phase.ended 81 | elseif MOAITouchSensor.TOUCH_CANCEL == eventType then 82 | phase = Phase.cancelled 83 | end 84 | l.layer.doListener({ 85 | phase = phase, 86 | location = {worldX,worldY}, 87 | previousLocation = l.deviceEvent.previousLocation, 88 | }) 89 | l.deviceEvent.previousLocation = {worldX,worldY} 90 | end 91 | end 92 | 93 | function device_pointer_callback(x, y) 94 | for k,l in pairs(sharedDeviceManager.layers) do 95 | l.deviceEvent.previousLocation = l.deviceEvent.lastLocation 96 | local worldX, worldY = l.layer.wrap:wndToWorld(x, y) 97 | l.deviceEvent.lastLocation = {worldX, worldY} 98 | if l.deviceEvent.hasPicked then 99 | l.layer.doListener({ 100 | phase = Phase.moved, 101 | location = {worldX, worldY}, 102 | previousLocation = l.deviceEvent.previousLocation, 103 | }) 104 | end 105 | end 106 | end 107 | 108 | function device_mouseLeft_callback(isDown) 109 | for k,l in pairs(sharedDeviceManager.layers) do 110 | local phase = nil 111 | if isDown then 112 | l.deviceEvent.hasPicked = true 113 | phase = Phase.began 114 | else 115 | phase = Phase.ended 116 | end 117 | if l.deviceEvent.hasPicked then 118 | l.layer.doListener({ 119 | phase = phase, 120 | location = l.deviceEvent.lastLocation, 121 | previousLocation = l.deviceEvent.previousLocation, 122 | }) 123 | if isDown then 124 | else 125 | l.deviceEvent.hasPicked = false 126 | end 127 | end 128 | end 129 | end 130 | 131 | function device_mouseRight_callback(isDown) 132 | end 133 | 134 | function device_mouseMiddle_callback(isDown) 135 | end 136 | -------------------------------------------------------------------------------- /moacat/Environment.lua: -------------------------------------------------------------------------------- 1 | -- Environment.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | 6 | Environment = {} 7 | 8 | local methods = String.split([[ 9 | getAppDisplayName 10 | getAppID 11 | getAppVersion 12 | getCacheDirectory 13 | getCarrierISOCountryCode 14 | getCarrierMobileCountryCode 15 | getCarrierMobileNetworkCode 16 | getCarrierName 17 | getConnectionType 18 | getCountryCode 19 | getCPUABI 20 | getDevBrand 21 | getDevName 22 | getDevManufacturer 23 | getDevModel 24 | getDevProduct 25 | getDocumentDirectory 26 | getLanguageCode 27 | getOSBrand 28 | getOSVersion 29 | getResourceDirectory 30 | getUDID 31 | getViewSize 32 | isRetinaDisplay 33 | ]], LF) 34 | 35 | for k,v in pairs(methods) do 36 | local value = MOAIEnvironment[v]() 37 | if String.start_with(v, 'get') then 38 | Environment[String.slice(v, 4, -1)] = value 39 | else 40 | Environment[v] = value 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /moacat/Event.lua: -------------------------------------------------------------------------------- 1 | -- Event.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | 7 | 8 | Phase = { 9 | began = 'began', 10 | moved = 'moved', 11 | ended = 'ended', 12 | cancelled = 'cancelled', 13 | } 14 | 15 | -------------------------------------------------------------------------------- /moacat/EventRecorder.lua: -------------------------------------------------------------------------------- 1 | -- EventRecorder.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | 6 | EventRecorder = extends(Object) 7 | 8 | function EventRecorder.initialize(self) 9 | end 10 | 11 | function EventRecorder.start(self) 12 | end 13 | 14 | function EventRecorder.stop(self) 15 | end 16 | 17 | function EventRecorder.replay(self) 18 | end 19 | 20 | function EventRecorder.save(self) 21 | end 22 | 23 | function EventRecorder.load(self) 24 | end 25 | -------------------------------------------------------------------------------- /moacat/Font.lua: -------------------------------------------------------------------------------- 1 | -- Font.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | 7 | Font = extends(MoaiNode) 8 | 9 | local DEFAULT_FONT_PATH = './fonts/arial-rounded.TTF' 10 | 11 | function Font.initialize(self) 12 | local mfont = MOAIFont.new () 13 | local charcodes = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,:;!?()&/-' 14 | mfont:loadFromTTF(DEFAULT_FONT_PATH, charcodes, 12, 163) 15 | self.wrap = mfont 16 | end 17 | -------------------------------------------------------------------------------- /moacat/Geometry.lua: -------------------------------------------------------------------------------- 1 | -- Geometry.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | Location = {} 6 | function Location.diff(a, b) 7 | return {a[1] - b[1], a[2] - b[2]} 8 | end 9 | function Location.multiplyOffset(loc, offset, mul) 10 | return {loc[1] + mul * offset[1], loc[2] + mul * offset[2]} 11 | end 12 | 13 | 14 | Rect = {} 15 | function Rect.unpack(rect) 16 | local origin = rect[1] 17 | local size = rect[2] 18 | return unpack({origin[1], origin[2], size[1], size[2]}) 19 | end 20 | 21 | function Rect.pack(xMin, yMin, xMax, yMax) 22 | return {{xMin,yMin},{xMax,yMax}} 23 | end 24 | 25 | function centered_rect_by_size(size) 26 | local halfWidth = size[1]/2 27 | local halfHeight = size[2]/2 28 | return {-halfWidth, -halfHeight, halfWidth, halfHeight} 29 | end 30 | -------------------------------------------------------------------------------- /moacat/Grid.lua: -------------------------------------------------------------------------------- 1 | -- Grid.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'MoaiNode' 6 | 7 | Grid = extends(MoaiNode) 8 | 9 | function Grid.initialize(self, cellSize) 10 | local mgrid = MOAIGrid.new() 11 | self._cellSize = cellSize or {1,1} 12 | self.wrap = mgrid 13 | end 14 | 15 | function Grid.getCellSize(self) 16 | return self._cellSize 17 | end 18 | 19 | function Grid.getRows(self) 20 | local width, height = self.wrap:getSize() 21 | local rows = {} 22 | for yTile = 1, height do 23 | local row = {} 24 | for xTile = 1, width do 25 | table.insert(row, self.wrap:getTile(xTile, yTile)) 26 | end 27 | table.insert(rows, row) 28 | end 29 | return rows 30 | end 31 | 32 | function Grid.setRows(self, rows) 33 | local width = 0 34 | local height = #rows 35 | if 0 < height then 36 | width = #rows[1] 37 | end 38 | local cellWidth = self._cellSize[1] 39 | local cellHeight = self._cellSize[2] 40 | self.wrap:setSize(width, height, cellWidth, cellHeight) 41 | for idx,row in ipairs(rows) do 42 | local t = {idx} 43 | for k,v in pairs(row) do 44 | table.insert(t, v) 45 | end 46 | self.wrap:setRow(unpack(t)) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /moacat/Image.lua: -------------------------------------------------------------------------------- 1 | -- Image.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'MoaiNode' 6 | 7 | Image = extends(MoaiNode) 8 | 9 | function Image.initialize(self, path) 10 | local mimage = MOAIImage.new() 11 | mimage:load(path, MOAIImage.TRUECOLOR + MOAIImage.PREMULTIPLY_ALPHA) 12 | self.path = path 13 | self.width, self.height = mimage:getSize() 14 | self.wrap = mimage 15 | end 16 | -------------------------------------------------------------------------------- /moacat/Label.lua: -------------------------------------------------------------------------------- 1 | -- Label.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | require 'MoaiNode' 7 | 8 | Label = extends(MoaiNode) 9 | 10 | function Label.initialize(self, text) 11 | Label.initWithText(self, text, MOAITextBox.LEFT_JUSTIFY) 12 | end 13 | 14 | function Label.setText(self, text) 15 | self.wrap:setString(text) 16 | self._text = text 17 | end 18 | 19 | function Label.getText(self) 20 | return self._text 21 | end 22 | 23 | function Label.initWithText(self, text, aligenment) 24 | local font = Font.new() 25 | local textSize = font.wrap:getScale() 26 | local mtextbox = MOAITextBox.new() 27 | mtextbox:setString(text) 28 | mtextbox:setTextSize(textSize) 29 | mtextbox:setFont(font.wrap) 30 | mtextbox:setAlignment(alignment) 31 | mtextbox:setYFlip(true) 32 | self.wrap = mtextbox 33 | self._text = text 34 | self._frame = {{0,0},{0,0}} 35 | end 36 | 37 | function Label.setOrigin(self, origin) 38 | self.setFrame({origin, self._frame[2]}) 39 | end 40 | 41 | function Label.getOrigin(self) 42 | return self._frame[1] 43 | end 44 | 45 | function Label.setSize(self, size) 46 | self.setFrame({self._frame[1], size}) 47 | end 48 | 49 | function Label.getSize(self) 50 | return self._frame[2] 51 | end 52 | 53 | function Label.setFrame(self, frame) 54 | local origin = frame[1] 55 | local size = frame[2] 56 | local x = origin[1] - Screen.halfWidth 57 | local y = -origin[2] + Screen.halfHeight - size[2] 58 | self.wrap:setRect(x, y, x+size[1], y+size[2]) 59 | self._frame = frame 60 | end 61 | 62 | function Label.getFrame(self) 63 | return self._frame 64 | end 65 | -------------------------------------------------------------------------------- /moacat/Layer.lua: -------------------------------------------------------------------------------- 1 | -- Layer.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'MoaiNode' 6 | require 'Device' 7 | require 'Viewport' 8 | 9 | Layer = extends(MoaiNode) 10 | 11 | function Layer.initialize(self, viewport) 12 | local mlayer = MOAILayer2D.new() 13 | mlayer:setViewport(viewport.wrap) 14 | self.props = {} 15 | self.wrap = mlayer 16 | end 17 | 18 | function Layer.add(self, prop) 19 | table.insert(self.props, prop) 20 | self.wrap:insertProp(prop.wrap) 21 | end 22 | 23 | function Layer.remove(self, prop) 24 | table.remove(self.props, prop) 25 | self.wrap:removeProp(prop.wrap) 26 | end 27 | 28 | function Layer.getPartition(self) 29 | return self.wrap:getPartition() 30 | end 31 | 32 | function Layer.setParallax(self, parallax) 33 | self.wrap:setParallax(unpack(parallax)) 34 | end 35 | 36 | function Layer.setCamera(self, transform) 37 | self.wrap:setCamera(transform.wrap) 38 | end 39 | 40 | function Layer.enableTouchEvents(self) 41 | Device.enableTouchEvents(self) 42 | end 43 | 44 | function Layer.disableTouchEvents(self) 45 | Device.disableTouchEvents(self) 46 | end 47 | 48 | function Layer.addExitButton(self) 49 | local button = TextButton.new("Exit", function() 50 | System.exit_after_seconds(0.1) 51 | end) 52 | button.frame = {{Screen.width - 110, 10}, {100,50}} 53 | self.add(button) 54 | end 55 | 56 | function Layer.coordForTopLeft(self) 57 | local xMin, yMin, xMax, yMax = self.wrap:getRect() 58 | local halfWidth = (xMax - xMin) / 2 59 | local halfHeight = (yMax - yMin) / 2 60 | return {{-halfWidth, -halfHeight}, {halfWidth, halfHeight}} 61 | end 62 | -------------------------------------------------------------------------------- /moacat/MoaiInfo.lua: -------------------------------------------------------------------------------- 1 | -- MoaiInfo.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | 6 | local IGNORE_METHODS = { 7 | 'getClassName', 'getClass', 8 | 'getAttrLink', -- MOAINode 9 | 'getFitting', 'getAttr', -- MOAILayer2D 10 | 'getTimesExecuted', -- MOAIAnim 11 | 'getValueAtTime', -- MOAIAnimCurve 12 | } 13 | function moai_properties(obj) 14 | local mt = getmetatable(obj) 15 | if nil == mt then 16 | return {} 17 | end 18 | local t = getmetatable(mt).__index 19 | local getters = {} 20 | local max_name_length = 0 21 | for k,v in pairs(t) do 22 | if String.start_with(k, 'get') then 23 | if Table.include(IGNORE_METHODS, k) then 24 | else 25 | max_name_length = math.max(#k, max_name_length) - 1 26 | table.insert(getters, k) 27 | end 28 | end 29 | end 30 | local result = {} 31 | local format = " %-" .. max_name_length .. "s %s" 32 | for k, getter in pairs(Table.sort(getters)) do 33 | local name = String.slice(getter, 4, -1) 34 | --log_info('name', name) 35 | local val = { obj[getter](obj) } 36 | local value = nil 37 | if 0 == #val then 38 | value = 'nil' 39 | elseif 1 == #val then 40 | value = tostring(val[1]) 41 | else 42 | value = inspect(val) 43 | end 44 | table.insert(result, " " .. SWF(format, name, value)) 45 | end 46 | return result 47 | end 48 | 49 | function inspect_moai_object(obj) 50 | local s = tostring(obj) 51 | local a = String.split(s, ' <') 52 | local result = "\n <" .. obj:getClassName() .. ": " .. 53 | String.slice(a[1], 3, -1) .. ">\n" .. 54 | Table.join(moai_properties(obj), LF) 55 | return result 56 | end 57 | 58 | function moai_info(...) 59 | local rest = {...} 60 | local ary = {} 61 | local found_moai_object = false 62 | for k,v in pairs(rest) do 63 | if nil == v.getClassName then 64 | table.insert(ary, v) 65 | else 66 | table.insert(ary, inspect_moai_object(v)) 67 | found_moai_object = true 68 | end 69 | end 70 | if found_moai_object then 71 | log_info(unpack(ary)) 72 | else 73 | log_info(...) 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /moacat/MoaiNode.lua: -------------------------------------------------------------------------------- 1 | -- MoaiNode.lua 2 | -- wookay.noh at gmail.com 3 | 4 | package.path = package.path .. ";../luacat/?.lua" 5 | require 'luacat' 6 | 7 | MoaiNode = extends(Object) 8 | 9 | function MoaiNode.initialize(self) 10 | self.wrap = nil 11 | self.listeners = nil 12 | end 13 | 14 | function MoaiNode.addListener(self, listener, callback) 15 | if nil == self.listeners then 16 | self.listeners = {} 17 | end 18 | table.insert(self.listeners, { 19 | listener = listener, 20 | callback = callback, 21 | }) 22 | end 23 | 24 | function MoaiNode.addEndedListener(self, callback) 25 | MoaiNode.addListener(self, function(event) 26 | if Phase.ended == event.phase then 27 | callback(event) 28 | end 29 | end) 30 | end 31 | 32 | function MoaiNode.doListener(self, event) 33 | if Layer == self.class then 34 | local mprop = self.partition:propForPoint(unpack(event.location)) 35 | if mprop then 36 | for k,p in pairs(self.props) do 37 | if mprop == p.wrap then 38 | p.doListener(Table.merge(event, {target=p})) 39 | break 40 | end 41 | end 42 | end 43 | end 44 | if self.listeners then 45 | for k,l in pairs(self.listeners) do 46 | l.listener(Table.merge(event, { 47 | target = self, 48 | callback = l.callback 49 | })) 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /moacat/PackagePath.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path .. ";../luacat/?.lua" 2 | -------------------------------------------------------------------------------- /moacat/Pen.lua: -------------------------------------------------------------------------------- 1 | -- Pen.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'Color' 6 | require 'Screen' 7 | require 'ScriptDeck' 8 | 9 | Pen = extends(Object) 10 | 11 | function Pen.initialize(self, layer) 12 | self.actions = {} 13 | self.color = Color.white 14 | self.width = 1 15 | self.layer = layer 16 | end 17 | 18 | function Pen.addPoint(self, point) -- {x,y} 19 | local action = { 20 | draw = MOAIDraw.drawPoints, 21 | data = point, 22 | pen = {color = self.color, width = self.width}, 23 | } 24 | table.insert(self.actions, action) 25 | end 26 | 27 | function Pen.addPoints(self, points) -- {{x,y},{x,y}} 28 | local action = { 29 | draw = MOAIDraw.drawPoints, 30 | data = Table.flatten(points), 31 | pen = {color = self.color, width = self.width}, 32 | } 33 | table.insert(self.actions, action) 34 | end 35 | 36 | function Pen.addLine(self, from, to) -- {x,y}, {x,y} 37 | local action = { 38 | draw = MOAIDraw.drawLine, 39 | data = Table.flatten({from,to}), 40 | pen = {color = self.color, width = self.width}, 41 | } 42 | table.insert(self.actions, action) 43 | end 44 | 45 | function Pen.addLines(self, lines) -- {{x,y},{x,y}} 46 | local action = { 47 | draw = MOAIDraw.drawLine, 48 | data = Table.flatten(lines), 49 | pen = {color = self.color, width = self.width}, 50 | } 51 | table.insert(self.actions, action) 52 | end 53 | 54 | function Pen.addRect(self, rect) 55 | local size = rect[2] 56 | local action = { 57 | draw = MOAIDraw.drawRect, 58 | data = centered_rect_by_size(size), 59 | pen = {color = self.color, width = self.width}, 60 | } 61 | table.insert(self.actions, action) 62 | end 63 | 64 | function Pen.addFilledRect(self, rect) 65 | local size = rect[2] 66 | local action = { 67 | draw = MOAIDraw.fillRect, 68 | data = centered_rect_by_size(size), 69 | pen = {color = self.color, width = self.width}, 70 | } 71 | table.insert(self.actions, action) 72 | end 73 | 74 | function Pen.addCircle(self, rect) 75 | local size = rect[2] 76 | local action = { 77 | draw = MOAIDraw.drawCircle, 78 | data = centered_rect_by_size(size), 79 | pen = {color = self.color, width = self.width}, 80 | } 81 | table.insert(self.actions, action) 82 | end 83 | 84 | function Pen.addFilledCircle(self, rect) 85 | local size = rect[2] 86 | local action = { 87 | draw = MOAIDraw.fillCircle, 88 | data = centered_rect_by_size(size), 89 | pen = {color = self.color, width = self.width}, 90 | } 91 | table.insert(self.actions, action) 92 | end 93 | 94 | local function draw_pen_actions(layer, actions, rect) 95 | local origin = rect[1] 96 | local size = rect[2] 97 | local scriptDeck = ScriptDeck.new(function() 98 | for k,action in pairs(actions) do 99 | MOAIGfxDevice.setPenColor(unpack(action.pen.color)) 100 | MOAIGfxDevice.setPenWidth(action.pen.width) 101 | action.draw(unpack(action.data)) 102 | end 103 | end, size) 104 | local prop = Prop.new(scriptDeck) 105 | prop.origin = origin 106 | layer.wrap:insertProp(prop.wrap) 107 | return prop 108 | end 109 | 110 | function Pen.draw_pen_actions(self, rect) 111 | draw_pen_actions(self.layer, self.actions, rect) 112 | end 113 | 114 | function Pen.drawRect(self, rect) 115 | self.addRect(rect) 116 | self.draw_pen_actions(rect) 117 | end 118 | 119 | function Pen.fillRect(self, rect) 120 | self.addFilledRect(rect) 121 | self.draw_pen_actions(rect) 122 | end 123 | -------------------------------------------------------------------------------- /moacat/Prop.lua: -------------------------------------------------------------------------------- 1 | -- Prop.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'MoaiNode' 6 | require 'Geometry' 7 | require 'Anim' 8 | 9 | Prop = extends(MoaiNode) 10 | 11 | function Prop.initialize(self, deck) 12 | local mprop = MOAIProp2D.new() 13 | mprop:setDeck(deck.wrap) 14 | self.deck = deck 15 | self._grid = nil 16 | self.wrap = mprop 17 | end 18 | 19 | function Prop.setDeckIndex(self, deckIndex) 20 | self.wrap:setIndex(deckIndex) 21 | end 22 | 23 | function Prop.setOrigin(self, origin) 24 | local size = self.deck.size 25 | local x = origin[1] - Screen.halfWidth + size[1]/2 26 | local y = -origin[2] + Screen.halfHeight - size[2]/2 27 | self.wrap:setLoc(x, y) 28 | end 29 | 30 | function Prop.getOrigin(self) 31 | local xMin, yMin, xMax, yMax = self.wrap:getRect() 32 | local xLoc, yLoc = self.wrap:getLoc() 33 | local x = Screen.halfWidth + xLoc + xMin 34 | local y = Screen.halfHeight - yLoc + yMin 35 | return {x,y} 36 | end 37 | 38 | function Prop.setParent(self, prop) 39 | self.wrap:setParent(prop.wrap) 40 | end 41 | 42 | function Prop.getLocation(self) 43 | return {self.wrap:getLoc()} 44 | end 45 | 46 | function Prop.setLocation(self, location) 47 | self.wrap:setLoc(unpack(location)) 48 | end 49 | 50 | function Prop.getPivot(self) 51 | return {self.wrap:getPiv()} 52 | end 53 | 54 | function Prop.setPivot(selfk, pivot) 55 | self.wrap:setPiv(unpack(pivot)) 56 | end 57 | 58 | function Prop.getScale(self) 59 | return {self.wrap:getScl()} 60 | end 61 | 62 | function Prop.setScale(self, scale) 63 | self.wrap:setScl(unpack(scale)) 64 | end 65 | 66 | function Prop.setGrid(self, grid) 67 | self._grid = grid 68 | self.wrap:setGrid(grid.wrap) 69 | end 70 | 71 | function Prop.getGrid(self) 72 | return self._grid 73 | end 74 | 75 | function Prop.setDeckRectDimension(self, dimension) 76 | self.deck.wrap:setRect(-dimension, dimension, dimension, -dimension) 77 | self.scale = {1, -1} 78 | end 79 | 80 | function Prop.animate(self, locations, duration) 81 | local anim = Anim.new(self) 82 | anim.setCurveWithLocations(locations, duration) 83 | return anim 84 | end 85 | 86 | 87 | -- listeners 88 | function Prop.drag_listener(event) 89 | event.target.wrap:addLoc(unpack( 90 | Location.diff(event.location, event.previousLocation))) 91 | if event.callback then 92 | event.callback(event) 93 | end 94 | end 95 | 96 | function Prop.ended_listener(event) 97 | if Phase.ended == event.phase then 98 | event.callback(event) 99 | end 100 | end 101 | -------------------------------------------------------------------------------- /moacat/Screen.lua: -------------------------------------------------------------------------------- 1 | -- Screen.lua 2 | -- wookay.noh at gmail.com 3 | 4 | Screen = { 5 | width = 320, 6 | height = 480, 7 | --width = 320, 8 | --height = 480, 9 | } 10 | Screen.frame = {{0,0},{Screen.width,Screen.height}} 11 | 12 | Screen.halfWidth = Screen.width / 2 13 | Screen.halfHeight = Screen.height / 2 14 | -------------------------------------------------------------------------------- /moacat/ScriptDeck.lua: -------------------------------------------------------------------------------- 1 | -- ScriptDeck.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | require 'MoaiNode' 7 | require 'Geometry' 8 | 9 | ScriptDeck = extends(Deck) 10 | 11 | function ScriptDeck.initialize(self, drawCallback, size) 12 | local mscriptDeck = MOAIScriptDeck.new() 13 | mscriptDeck:setDrawCallback(drawCallback) 14 | mscriptDeck:setRect(unpack(centered_rect_by_size(size))) 15 | self.size = size 16 | self.wrap = mscriptDeck 17 | end 18 | -------------------------------------------------------------------------------- /moacat/Sim.lua: -------------------------------------------------------------------------------- 1 | -- Sim.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | require 'System' 7 | require 'Layer' 8 | 9 | Sim = extends(Object) 10 | 11 | function Sim.push(layer) 12 | MOAISim.pushRenderPass(layer.wrap) 13 | end 14 | 15 | function Sim.layer() 16 | System.openWindow() 17 | 18 | local viewport = Viewport.new() 19 | local layer = Layer.new(viewport) 20 | Sim.push(layer) 21 | return layer 22 | end 23 | -------------------------------------------------------------------------------- /moacat/Sprite.lua: -------------------------------------------------------------------------------- 1 | -- Sprite.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'MoaiNode' 6 | 7 | Sprite = extends(MoaiNode) 8 | 9 | function Sprite.initialize(self, prop, opt) 10 | local opt = opt or { interval = 0.2 } 11 | local mcurve = MOAIAnimCurve.new() 12 | local num = prop.deck.deckSize[1] * prop.deck.deckSize[2] 13 | mcurve:reserveKeys ( num ) 14 | local t = 0.00 15 | for idx=1, num, 1 do 16 | mcurve:setKey ( idx, t, idx, MOAIEaseType.FLAT ) 17 | t = t + opt.interval 18 | end 19 | 20 | local manim = MOAIAnim:new() 21 | manim:reserveLinks(1) 22 | manim:setLink(1, mcurve, prop.wrap, MOAIProp2D.ATTR_INDEX) 23 | manim:setMode(MOAITimer.LOOP) 24 | 25 | self.prop = prop 26 | self.manim = manim 27 | end 28 | 29 | function Sprite.play(self) 30 | self.manim:start() 31 | end 32 | 33 | function Sprite.pause(self) 34 | self.manim:stop() 35 | end 36 | -------------------------------------------------------------------------------- /moacat/System.lua: -------------------------------------------------------------------------------- 1 | -- System.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | require 'Screen' 7 | require 'Debug' 8 | 9 | System = extends(Object) 10 | 11 | function System.openWindow() 12 | Debug.setLogLevelAsNone() 13 | Debug.showLines() 14 | --Debug.setHistogramEnabled() 15 | 16 | MOAISim.openWindow("sim", Screen.width, Screen.height) 17 | end 18 | 19 | 20 | function System.exit() 21 | if Debug.HistogramEnabled then 22 | MOAISim.forceGarbageCollection() 23 | MOAISim.reportHistogram() 24 | end 25 | print('exit') 26 | os.exit() 27 | end 28 | 29 | function System.exit_after_seconds(delay) 30 | local timer = MOAITimer.new() 31 | timer:setSpan(delay) 32 | timer:setListener(MOAITimer.EVENT_TIMER_LOOP, 33 | function() 34 | timer:stop() 35 | timer = nil 36 | System.exit() 37 | end 38 | ) 39 | timer:start() 40 | end 41 | 42 | function is_main() 43 | return nil == IsMain 44 | end 45 | -------------------------------------------------------------------------------- /moacat/TextButton.lua: -------------------------------------------------------------------------------- 1 | -- TextButton.lua 2 | -- wookay.noh at gmail.com 3 | 4 | 5 | require 'luacat' 6 | require 'Button' 7 | require 'Label' 8 | require 'Screen' 9 | 10 | TextButton = extends(Label) 11 | 12 | function TextButton.initialize(self, text, callback) 13 | MoaiNode.addEndedListener(self, callback) 14 | Label.initWithText(self, text, MOAITextBox.CENTER_JUSTIFY) 15 | end 16 | -------------------------------------------------------------------------------- /moacat/Transform.lua: -------------------------------------------------------------------------------- 1 | -- Transform.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'MoaiNode' 6 | 7 | Transform = extends(MoaiNode) 8 | 9 | function Transform.initialize(self) 10 | local mtransform = MOAITransform.new() 11 | self.wrap = mtransform 12 | end 13 | 14 | function Transform.getLocation(self) 15 | local x, y = self.wrap:getLoc() 16 | return {x,y} 17 | end 18 | 19 | function Transform.setLocation(self, location) 20 | return self.wrap:setLoc(unpack(location)) 21 | end 22 | 23 | function Transform.seekLocation(self, location, length) 24 | local x = location[1] 25 | local y = location[2] 26 | return self.wrap:seekLoc(x, y, length or 1) 27 | end 28 | -------------------------------------------------------------------------------- /moacat/Viewport.lua: -------------------------------------------------------------------------------- 1 | -- Viewport.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'luacat' 5 | require 'Screen' 6 | require 'MoaiNode' 7 | 8 | Viewport = extends(MoaiNode) 9 | 10 | function Viewport.initialize(self) 11 | local mviewport = MOAIViewport.new() 12 | mviewport:setSize(Screen.width, Screen.height) 13 | mviewport:setScale(Screen.width, Screen.height) 14 | self.wrap = mviewport 15 | end 16 | -------------------------------------------------------------------------------- /moacat/moacat.lua: -------------------------------------------------------------------------------- 1 | -- moacat.lua 2 | -- wookay.noh at gmail.com 3 | 4 | require 'PackagePath' 5 | require 'luacat' 6 | 7 | require 'Screen' 8 | require 'System' 9 | require 'MoaiInfo' 10 | require 'Color' 11 | require 'Environment' 12 | require 'Pen' 13 | require 'Sim' 14 | require 'Device' 15 | require 'Event' 16 | require 'Geometry' 17 | 18 | require 'MoaiNode' 19 | require 'Viewport' 20 | require 'Transform' 21 | require 'Layer' 22 | require 'Deck' 23 | require 'Anim' 24 | require 'Prop' 25 | require 'Sprite' 26 | require 'Button' 27 | require 'TextButton' 28 | require 'Font' 29 | require 'Label' 30 | require 'Grid' 31 | --------------------------------------------------------------------------------