nakor 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.md +36 -0
- data/Rakefile +0 -1
- data/features/generate.feature +9 -3
- data/features/step_definitions/generate_steps.rb +4 -0
- data/features/update.feature +19 -0
- data/lib/nakor/cli.rb +5 -0
- data/lib/nakor/generators/app.rb +20 -3
- data/lib/nakor/generators/corona-game-template/active_record.lua +155 -0
- data/lib/nakor/generators/corona-game-template/geometry.lua +76 -0
- data/lib/nakor/generators/corona-game-template/middleclass.lua +139 -0
- data/lib/nakor/generators/corona-game-template/orm.lua +49 -17
- data/lib/nakor/generators/corona-game-template/radlib.lua +3 -1
- data/lib/nakor/generators/corona-game-template/sql.lua +79 -0
- data/lib/nakor/utilities/update_rad_lib.rb +9 -0
- data/lib/nakor/version.rb +1 -1
- data/nakor.gemspec +0 -1
- metadata +21 -22
data/.gitignore
CHANGED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Nakor
|
2
|
+
|
3
|
+
Nakor is a Ruby gem for generating a template application for Corona SDK. It creates a template app with a splash screen, a menu with four buttons (Play, Settings, Help, About), and one scene for each of the four buttons. It uses Corona SDK's built-in Storyboard to manage scenes.
|
4
|
+
|
5
|
+
The generated app also includes [RadLib](https://github.com/radamanthus/radlib), a library of utility Lua functions to support Corona SDK development.
|
6
|
+
|
7
|
+
# Installation
|
8
|
+
|
9
|
+
gem install nakor
|
10
|
+
|
11
|
+
|
12
|
+
# Usage
|
13
|
+
|
14
|
+
nakor generate awesome_app
|
15
|
+
|
16
|
+
This will create the *awesome_app* directory in the current directory. To run it in Corona simulator:
|
17
|
+
|
18
|
+
cd awesome_app
|
19
|
+
/Applications/CoronaSDK/simulator awesome_app
|
20
|
+
|
21
|
+
The generated project directory structure looks like this:
|
22
|
+
|
23
|
+
appname
|
24
|
+
+-- assets
|
25
|
+
+-- appname
|
26
|
+
+-- doc
|
27
|
+
+-- server
|
28
|
+
|
29
|
+
The directory structure follows my personal convention for mobile projects:
|
30
|
+
|
31
|
+
- All mobile app code is in appname/appname.
|
32
|
+
- If this has a server component, the server app source code is in appname/server
|
33
|
+
- Game assets (e.g. Illustrator .ai files) are in appname/assets, finished PNGs are copied over to appname/appname because that's where Corona SDK expects them to be.
|
34
|
+
- The game design document (yes you should have one) and all other documentation are in appname/doc
|
35
|
+
|
36
|
+
|
data/Rakefile
CHANGED
data/features/generate.feature
CHANGED
@@ -1,12 +1,18 @@
|
|
1
1
|
Feature: Generate
|
2
2
|
In order to make the world a better place
|
3
|
-
As a
|
3
|
+
As a Corona SDK programmer
|
4
4
|
I want to be able to generate new apps
|
5
5
|
|
6
|
-
Scenario: Generate a new app in a non-
|
7
|
-
When I run `../../bin/nakor generate awesome_game`
|
6
|
+
Scenario: Generate a new app in a non-existent folder
|
7
|
+
When I run `../../bin/nakor generate 'awesome_game'`
|
8
8
|
Then the output should contain "Successfully generated 'awesome_game'"
|
9
9
|
And the following files should exist:
|
10
10
|
| awesome_game/main.lua |
|
11
11
|
|
12
12
|
Scenario: Warn the user when generating an app will overwrite an existing folder
|
13
|
+
|
14
|
+
Scenario: Run the generated app
|
15
|
+
When I run `../../bin/nakor generate 'awesome_game'`
|
16
|
+
And I run `simulator awesome_game` interactively
|
17
|
+
Then the "awesome_game" app should run without errors
|
18
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Generate
|
2
|
+
In order to make the world a better place
|
3
|
+
As a Corona SDK programmer
|
4
|
+
I want to be able to update my apps to the latest version of RadLib
|
5
|
+
|
6
|
+
Scenario: Refuse to update a non-existen app
|
7
|
+
|
8
|
+
Scenario: Update RadLib inside an existing app
|
9
|
+
When I run `../../bin/nakor update_radlib 'awesome_game'`
|
10
|
+
Then the output should contain "Successfully updated 'awesome_game'"
|
11
|
+
And the following files should exist:
|
12
|
+
| awesome_game/main.lua |
|
13
|
+
|
14
|
+
Scenario: Run the generated app
|
15
|
+
When I run `../../bin/nakor update_radlib 'awesome_game'`
|
16
|
+
And I run `simulator awesome_game` interactively
|
17
|
+
Then the "awesome_game" app should run without errors
|
18
|
+
|
19
|
+
|
data/lib/nakor/cli.rb
CHANGED
@@ -7,5 +7,10 @@ module Nakor
|
|
7
7
|
def generate(app_name)
|
8
8
|
Nakor::Generators::App.start([app_name])
|
9
9
|
end
|
10
|
+
|
11
|
+
desc "update_radlib APP_DIR", "updates radlib inside an existing application"
|
12
|
+
def update_radlib(app_dir)
|
13
|
+
Nakor::Utilities::UpdateRadLib.execute([app_dir])
|
14
|
+
end
|
10
15
|
end
|
11
16
|
end
|
data/lib/nakor/generators/app.rb
CHANGED
@@ -17,19 +17,23 @@ module Nakor
|
|
17
17
|
|
18
18
|
TEMPLATE_FILES = %W{
|
19
19
|
about.lua
|
20
|
+
active_record.lua
|
20
21
|
build.settings
|
21
22
|
config.lua
|
23
|
+
geometry.lua
|
22
24
|
help.lua
|
23
25
|
init_buttons.lua
|
24
26
|
io_ext.lua
|
25
27
|
loadmenu.lua
|
26
28
|
main.lua
|
27
29
|
menu.lua
|
30
|
+
middleclass.lua
|
28
31
|
orm.lua
|
29
32
|
play.lua
|
30
33
|
radlib.lua
|
31
34
|
README
|
32
35
|
settings.lua
|
36
|
+
sql.lua
|
33
37
|
string_ext.lua
|
34
38
|
table_ext.lua
|
35
39
|
time_ext.lua
|
@@ -46,24 +50,37 @@ module Nakor
|
|
46
50
|
end
|
47
51
|
|
48
52
|
def create_group
|
49
|
-
|
53
|
+
# Create the top-level app directory
|
54
|
+
empty_directory app_name
|
55
|
+
|
56
|
+
# Create the subdirectories
|
57
|
+
create_subdirectory app_name
|
58
|
+
create_subdirectory "server"
|
59
|
+
create_subdirectory "assets"
|
60
|
+
create_subdirectory "doc"
|
50
61
|
end
|
51
62
|
|
52
63
|
def copy_source_files
|
53
64
|
TEMPLATE_FILES.each do |template_file|
|
54
|
-
template template_file, "#{app_name}/#{template_file}"
|
65
|
+
template template_file, "#{app_name}/#{app_name}/#{template_file}"
|
55
66
|
end
|
56
67
|
end
|
57
68
|
|
58
69
|
def copy_asset_files
|
59
70
|
ASSET_FILES.each do |asset_file|
|
60
|
-
copy_file asset_file, "#{app_name}/#{asset_file}"
|
71
|
+
copy_file asset_file, "#{app_name}/#{app_name}/#{asset_file}"
|
61
72
|
end
|
62
73
|
end
|
63
74
|
|
64
75
|
def done
|
65
76
|
puts "Successfully generated '#{app_name}'"
|
66
77
|
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def create_subdirectory(subdir)
|
82
|
+
empty_directory(File.join app_name, subdir)
|
83
|
+
end
|
67
84
|
end
|
68
85
|
end
|
69
86
|
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
-- USAGE
|
2
|
+
--
|
3
|
+
-- Create a Lua file for your module. The file should look like this:
|
4
|
+
--
|
5
|
+
-- require 'ActiveRecord'
|
6
|
+
-- Product = ActiveRecord:subclass('ActiveRecord')
|
7
|
+
-- Product.tableName = 'products'
|
8
|
+
-- Product.tableFields = {
|
9
|
+
-- id = {type = 'integer', flags = {'primary_key', 'autoincrement', 'not_null'} },
|
10
|
+
-- name = {type = 'string', flags = {'not_null'} }
|
11
|
+
-- }
|
12
|
+
--
|
13
|
+
-- If the table does not yet exist, you can create it in your app initialization with this call:
|
14
|
+
--
|
15
|
+
-- orm.initialize()
|
16
|
+
-- Product.createTable()
|
17
|
+
--
|
18
|
+
-- Sample API calls
|
19
|
+
--
|
20
|
+
-- local products = Product.findAll
|
21
|
+
--
|
22
|
+
-- p = Product.new{id = 1, name = 'test', description = ''} (NOT YET IMPLEMENTED)
|
23
|
+
-- p.save
|
24
|
+
--
|
25
|
+
-- p.updateAttribute('name', 'newName')
|
26
|
+
-- p.updateAttributes{name = 'newName', description = 'newDescription'} (NOT YET IMPLEMENTED)
|
27
|
+
--
|
28
|
+
-- p = Product.find(1)
|
29
|
+
-- test_products = Product.where("name = 'test'")
|
30
|
+
--
|
31
|
+
-- numberOfProducts = Product.count()
|
32
|
+
--
|
33
|
+
|
34
|
+
require 'middleclass'
|
35
|
+
local orm = require 'orm'
|
36
|
+
local sql = require 'sql'
|
37
|
+
|
38
|
+
ActiveRecord = class('ActiveRecord')
|
39
|
+
|
40
|
+
------------------------------------------------------------------------------
|
41
|
+
-- CLASS (STATIC) METHODS - START
|
42
|
+
------------------------------------------------------------------------------
|
43
|
+
function ActiveRecord:initialize(newRecord)
|
44
|
+
for k,v in pairs(newRecord) do
|
45
|
+
self[k] = v
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
------------------------------------------------------------------------------
|
50
|
+
-- Returns the number of rows in the table
|
51
|
+
------------------------------------------------------------------------------
|
52
|
+
function ActiveRecord.static:count()
|
53
|
+
return orm.getTableRowCount(self.tableName)
|
54
|
+
end
|
55
|
+
|
56
|
+
------------------------------------------------------------------------------
|
57
|
+
-- Creates the table
|
58
|
+
-- TODO: If options.recreate = true, it drops the table if it already exists
|
59
|
+
------------------------------------------------------------------------------
|
60
|
+
function ActiveRecord.static:createTable(options)
|
61
|
+
local createSql = sql.generateCreateTable(self.tableName, self.tableFields)
|
62
|
+
db:exec( createSql )
|
63
|
+
end
|
64
|
+
|
65
|
+
------------------------------------------------------------------------------
|
66
|
+
-- Returns the record matching the given id. Returns nil if no match is found.
|
67
|
+
--
|
68
|
+
-- NOTE: Until I figure out how to determine the caller's class,
|
69
|
+
-- I'll have to resort to this ugliness of using the klass parameter
|
70
|
+
------------------------------------------------------------------------------
|
71
|
+
function ActiveRecord.static:find(klass, id)
|
72
|
+
local record = orm.selectOne(klass.tableName, 'id', id)
|
73
|
+
if not( record == nil ) then
|
74
|
+
result = klass:new(record)
|
75
|
+
end
|
76
|
+
return result
|
77
|
+
end
|
78
|
+
|
79
|
+
------------------------------------------------------------------------------
|
80
|
+
-- Returns all rows in the table that match the given filter
|
81
|
+
------------------------------------------------------------------------------
|
82
|
+
function ActiveRecord.static:findAll( filter, orderBy )
|
83
|
+
local result = nil
|
84
|
+
if filter == nil then
|
85
|
+
result = orm.selectAll( self.tableName, {order = orderBy} )
|
86
|
+
else
|
87
|
+
result = orm.selectWhere( self.tableName, {where = filter, order = orderBy} )
|
88
|
+
end
|
89
|
+
return result
|
90
|
+
end
|
91
|
+
|
92
|
+
------------------------------------------------------------------------------
|
93
|
+
-- Updates all rows in the table that match the given filter
|
94
|
+
------------------------------------------------------------------------------
|
95
|
+
function ActiveRecord.static:updateAll( updateSql, filter )
|
96
|
+
if filter == nil then
|
97
|
+
orm.updateAll( self.tableName, updateSql )
|
98
|
+
else
|
99
|
+
orm.updateWhere( self.tableName, updateSql, filter )
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
------------------------------------------------------------------------------
|
104
|
+
-- CLASS (STATIC) METHODS - END
|
105
|
+
------------------------------------------------------------------------------
|
106
|
+
|
107
|
+
|
108
|
+
------------------------------------------------------------------------------
|
109
|
+
-- INSTANCE METHODS - START
|
110
|
+
------------------------------------------------------------------------------
|
111
|
+
|
112
|
+
------------------------------------------------------------------------------
|
113
|
+
-- Reloads the record values from the database
|
114
|
+
------------------------------------------------------------------------------
|
115
|
+
function ActiveRecord:reload()
|
116
|
+
local updatedRecord = orm.selectOne( self.class.tableName, 'id', self.id )
|
117
|
+
for k,v in pairs(updatedRecord) do
|
118
|
+
self[k] = v
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
------------------------------------------------------------------------------
|
123
|
+
-- Saves the content of the object to the database.
|
124
|
+
-- If a matching record already exists in the database, an UPDATE is done.
|
125
|
+
-- Otherwise an INSERT is done.
|
126
|
+
------------------------------------------------------------------------------
|
127
|
+
function ActiveRecord:save()
|
128
|
+
local updateTable = {}
|
129
|
+
for k in pairs(self.class.tableFields) do
|
130
|
+
updateTable[k] = self[k]
|
131
|
+
end
|
132
|
+
orm.createOrUpdate( self.class.tableName, updateTable )
|
133
|
+
end
|
134
|
+
|
135
|
+
------------------------------------------------------------------------------
|
136
|
+
-- Updates one column value
|
137
|
+
------------------------------------------------------------------------------
|
138
|
+
function ActiveRecord:updateAttribute( columnName, columnValue )
|
139
|
+
local filter = "id = " .. self.id
|
140
|
+
orm.updateAttribute( self.class.tableName, filter, columnName, columnValue )
|
141
|
+
end
|
142
|
+
|
143
|
+
------------------------------------------------------------------------------
|
144
|
+
-- Updates an array of columns
|
145
|
+
------------------------------------------------------------------------------
|
146
|
+
function ActiveRecord:updateAttributes( updateTable )
|
147
|
+
print("IMPLEMENTATION PENDING...")
|
148
|
+
end
|
149
|
+
|
150
|
+
------------------------------------------------------------------------------
|
151
|
+
-- INSTANCE METHODS - END
|
152
|
+
------------------------------------------------------------------------------
|
153
|
+
|
154
|
+
|
155
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
local M = {}
|
2
|
+
|
3
|
+
------------------------------------------------------------
|
4
|
+
-- Public: checks if the given point is inside the given container
|
5
|
+
--
|
6
|
+
-- Assumptions:
|
7
|
+
-- The container has the properties: top, left, bottom, right
|
8
|
+
-- The point has the properties x, y
|
9
|
+
--
|
10
|
+
-- Returns:
|
11
|
+
-- true if the point is inside the container
|
12
|
+
-- false if not
|
13
|
+
------------------------------------------------------------
|
14
|
+
local pointIsInside = function(point, rectangle)
|
15
|
+
if (
|
16
|
+
(point.x >= rectangle.left) and
|
17
|
+
(point.x <= rectangle.right) and
|
18
|
+
(point.y >= rectangle.top) and
|
19
|
+
(point.y <= rectangle.bottom)
|
20
|
+
) then
|
21
|
+
return true
|
22
|
+
else
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
M.pointIsInside = pointIsInside
|
27
|
+
|
28
|
+
------------------------------------------------------------
|
29
|
+
-- Public: checks if the given rectangle is completely
|
30
|
+
-- inside the given rectangular container
|
31
|
+
--
|
32
|
+
-- Assumptions:
|
33
|
+
-- Both container and object have the properties: top, left, bottom, right
|
34
|
+
--
|
35
|
+
-- Returns:
|
36
|
+
-- true if the both (top,left) and (bottom,right)
|
37
|
+
-- of the rectangle are inside the container
|
38
|
+
-- false otherwise
|
39
|
+
------------------------------------------------------------
|
40
|
+
local rectIsInside = function(object, container)
|
41
|
+
if pointIsInside({x = object.left, y = object.top}, container) and
|
42
|
+
pointIsInside({x = object.right, y = object.bottom}, container) then
|
43
|
+
return true
|
44
|
+
else
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
M.rectIsInside = rectIsInside
|
49
|
+
|
50
|
+
------------------------------------------------------------
|
51
|
+
-- Public: checks if the given rectangle is at at least partially
|
52
|
+
-- inside the given rectangular container
|
53
|
+
--
|
54
|
+
-- Assumption:
|
55
|
+
-- Both container and object have the properties: top, left, bottom, right
|
56
|
+
--
|
57
|
+
-- Returns:
|
58
|
+
-- true if at least one of the corners of the rectangle
|
59
|
+
-- is inside the container
|
60
|
+
-- false otherwise
|
61
|
+
------------------------------------------------------------
|
62
|
+
local rectIsPartiallyInside = function(object, container)
|
63
|
+
if pointIsInside({x = object.left, y = object.top}, container) or
|
64
|
+
pointIsInside({x = object.right, y = object.top}, container) or
|
65
|
+
pointIsInside({x = object.left, y = object.bottom}, container) or
|
66
|
+
pointIsInside({x = object.right, y = object.bottom}, container) then
|
67
|
+
return true
|
68
|
+
else
|
69
|
+
return false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
M.rectIsPartiallyInside = rectIsPartiallyInside
|
73
|
+
|
74
|
+
return M
|
75
|
+
|
76
|
+
|
@@ -0,0 +1,139 @@
|
|
1
|
+
-- middleclass.lua - v2.0 (2011-09)
|
2
|
+
-- Copyright (c) 2011 Enrique García Cota
|
3
|
+
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
5
|
+
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
6
|
+
-- Based on YaciCode, from Julien Patte and LuaObject, from Sebastien Rocca-Serra
|
7
|
+
|
8
|
+
local _classes = setmetatable({}, {__mode = "k"})
|
9
|
+
|
10
|
+
local function _setClassDictionariesMetatables(klass)
|
11
|
+
local dict = klass.__instanceDict
|
12
|
+
dict.__index = dict
|
13
|
+
|
14
|
+
local super = klass.super
|
15
|
+
if super then
|
16
|
+
local superStatic = super.static
|
17
|
+
setmetatable(dict, super.__instanceDict)
|
18
|
+
setmetatable(klass.static, { __index = function(_,k) return dict[k] or superStatic[k] end })
|
19
|
+
else
|
20
|
+
setmetatable(klass.static, { __index = function(_,k) return dict[k] end })
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
local function _setClassMetatable(klass)
|
25
|
+
setmetatable(klass, {
|
26
|
+
__tostring = function() return "class " .. klass.name end,
|
27
|
+
__index = klass.static,
|
28
|
+
__newindex = klass.__instanceDict,
|
29
|
+
__call = function(self, ...) return self:new(...) end
|
30
|
+
})
|
31
|
+
end
|
32
|
+
|
33
|
+
local function _createClass(name, super)
|
34
|
+
local klass = { name = name, super = super, static = {}, __mixins = {}, __instanceDict={} }
|
35
|
+
klass.subclasses = setmetatable({}, {__mode = "k"})
|
36
|
+
|
37
|
+
_setClassDictionariesMetatables(klass)
|
38
|
+
_setClassMetatable(klass)
|
39
|
+
_classes[klass] = true
|
40
|
+
|
41
|
+
return klass
|
42
|
+
end
|
43
|
+
|
44
|
+
local function _createLookupMetamethod(klass, name)
|
45
|
+
return function(...)
|
46
|
+
local method = klass.super[name]
|
47
|
+
assert( type(method)=='function', tostring(klass) .. " doesn't implement metamethod '" .. name .. "'" )
|
48
|
+
return method(...)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
local function _setClassMetamethods(klass)
|
53
|
+
for _,m in ipairs(klass.__metamethods) do
|
54
|
+
klass[m]= _createLookupMetamethod(klass, m)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
local function _setDefaultInitializeMethod(klass, super)
|
59
|
+
klass.initialize = function(instance, ...)
|
60
|
+
return super.initialize(instance, ...)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
local function _includeMixin(klass, mixin)
|
65
|
+
assert(type(mixin)=='table', "mixin must be a table")
|
66
|
+
for name,method in pairs(mixin) do
|
67
|
+
if name ~= "included" and name ~= "static" then klass[name] = method end
|
68
|
+
end
|
69
|
+
if mixin.static then
|
70
|
+
for name,method in pairs(mixin.static) do
|
71
|
+
klass.static[name] = method
|
72
|
+
end
|
73
|
+
end
|
74
|
+
if type(mixin.included)=="function" then mixin:included(klass) end
|
75
|
+
klass.__mixins[mixin] = true
|
76
|
+
end
|
77
|
+
|
78
|
+
Object = _createClass("Object", nil)
|
79
|
+
|
80
|
+
Object.static.__metamethods = { '__add', '__call', '__concat', '__div', '__le', '__lt',
|
81
|
+
'__mod', '__mul', '__pow', '__sub', '__tostring', '__unm' }
|
82
|
+
|
83
|
+
function Object.static:allocate()
|
84
|
+
assert(_classes[self], "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
|
85
|
+
return setmetatable({ class = self }, self.__instanceDict)
|
86
|
+
end
|
87
|
+
|
88
|
+
function Object.static:new(...)
|
89
|
+
local instance = self:allocate()
|
90
|
+
instance:initialize(...)
|
91
|
+
return instance
|
92
|
+
end
|
93
|
+
|
94
|
+
function Object.static:subclass(name)
|
95
|
+
assert(_classes[self], "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'")
|
96
|
+
assert(type(name) == "string", "You must provide a name(string) for your class")
|
97
|
+
|
98
|
+
local subclass = _createClass(name, self)
|
99
|
+
_setClassMetamethods(subclass)
|
100
|
+
_setDefaultInitializeMethod(subclass, self)
|
101
|
+
self.subclasses[subclass] = true
|
102
|
+
self:subclassed(subclass)
|
103
|
+
|
104
|
+
return subclass
|
105
|
+
end
|
106
|
+
|
107
|
+
function Object.static:subclassed(other) end
|
108
|
+
|
109
|
+
function Object.static:include( ... )
|
110
|
+
assert(_classes[self], "Make sure you that you are using 'Class:include' instead of 'Class.include'")
|
111
|
+
for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end
|
112
|
+
return self
|
113
|
+
end
|
114
|
+
|
115
|
+
function Object:initialize() end
|
116
|
+
|
117
|
+
function Object:__tostring() return "instance of " .. tostring(self.class) end
|
118
|
+
|
119
|
+
function class(name, super, ...)
|
120
|
+
super = super or Object
|
121
|
+
return super:subclass(name, ...)
|
122
|
+
end
|
123
|
+
|
124
|
+
function instanceOf(aClass, obj)
|
125
|
+
if not _classes[aClass] or type(obj) ~= 'table' or not _classes[obj.class] then return false end
|
126
|
+
if obj.class == aClass then return true end
|
127
|
+
return subclassOf(aClass, obj.class)
|
128
|
+
end
|
129
|
+
|
130
|
+
function subclassOf(other, aClass)
|
131
|
+
if not _classes[aClass] or not _classes[other] or aClass.super == nil then return false end
|
132
|
+
return aClass.super == other or subclassOf(other, aClass.super)
|
133
|
+
end
|
134
|
+
|
135
|
+
function includes(mixin, aClass)
|
136
|
+
if not _classes[aClass] then return false end
|
137
|
+
if aClass.__mixins[mixin] then return true end
|
138
|
+
return includes(mixin, aClass.super)
|
139
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
local sql = require 'sql'
|
1
2
|
local sqlite3 = require "sqlite3"
|
2
3
|
local radlib = require "radlib"
|
3
4
|
|
@@ -9,9 +10,9 @@ local M = {}
|
|
9
10
|
------------------------------------------------------------------------------
|
10
11
|
local initialize = function( dbPath )
|
11
12
|
if dbPath ~= nil then
|
12
|
-
db = sqlite3.open( dbPath )
|
13
|
+
_G.db = sqlite3.open( dbPath )
|
13
14
|
else
|
14
|
-
db = sqlite3.open_memory()
|
15
|
+
_G.db = sqlite3.open_memory()
|
15
16
|
end
|
16
17
|
return db
|
17
18
|
end
|
@@ -21,16 +22,21 @@ M.initialize = initialize
|
|
21
22
|
-- Close the database
|
22
23
|
------------------------------------------------------------------------------
|
23
24
|
local close = function()
|
24
|
-
db:close()
|
25
|
+
_G.db:close()
|
25
26
|
end
|
26
27
|
M.close = close
|
27
28
|
|
28
29
|
------------------------------------------------------------------------------
|
29
30
|
-- Return all the contents of an SQLite table as a table structure
|
30
31
|
------------------------------------------------------------------------------
|
31
|
-
local selectAll = function(tableName)
|
32
|
+
local selectAll = function( tableName, params )
|
32
33
|
local result = {}
|
33
|
-
|
34
|
+
local s = sql.generateSelect({
|
35
|
+
tableName = tableName,
|
36
|
+
order = params.order,
|
37
|
+
limit = params.limit
|
38
|
+
})
|
39
|
+
for row in _G.db:nrows(s) do
|
34
40
|
result[#result+1] = row
|
35
41
|
end
|
36
42
|
return result
|
@@ -41,9 +47,15 @@ M.selectAll = selectAll
|
|
41
47
|
-- Return contents of an SQLite table filtered by a WHERE query
|
42
48
|
-- Return value is a table structure
|
43
49
|
------------------------------------------------------------------------------
|
44
|
-
local selectWhere = function(tableName,
|
50
|
+
local selectWhere = function(tableName, params )
|
45
51
|
local result = {}
|
46
|
-
|
52
|
+
local s = sql.generateSelect({
|
53
|
+
tableName = tableName,
|
54
|
+
where = params.where,
|
55
|
+
order = params.order,
|
56
|
+
limit = params.limit
|
57
|
+
})
|
58
|
+
for row in _G.db:nrows(s) do
|
47
59
|
result[#result+1] = row
|
48
60
|
end
|
49
61
|
return result
|
@@ -56,10 +68,12 @@ M.selectWhere = selectWhere
|
|
56
68
|
------------------------------------------------------------------------------
|
57
69
|
local selectOne = function(tableName, key, keyValue)
|
58
70
|
local result = {}
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
71
|
+
local s = sql.generateSelect({
|
72
|
+
tableName = tableName,
|
73
|
+
where = key .. " = " .. keyValue,
|
74
|
+
limit = 1
|
75
|
+
})
|
76
|
+
for row in _G.db:nrows(s) do
|
63
77
|
result[1] = row
|
64
78
|
break
|
65
79
|
end
|
@@ -72,7 +86,7 @@ M.selectOne = selectOne
|
|
72
86
|
------------------------------------------------------------------------------
|
73
87
|
local getTableRowCount = function(tableName)
|
74
88
|
local rowCount = 0
|
75
|
-
for row in db:nrows("SELECT COUNT(*) as rowcount FROM " .. tableName) do
|
89
|
+
for row in _G.db:nrows("SELECT COUNT(*) as rowcount FROM " .. tableName) do
|
76
90
|
rowCount = row.rowcount
|
77
91
|
end
|
78
92
|
return rowCount
|
@@ -107,8 +121,7 @@ local insertRow = function( tableName, row )
|
|
107
121
|
local sql = "INSERT INTO " .. tableName .. columnList .. valuesList
|
108
122
|
|
109
123
|
-- execute the SQL command for inserting the row
|
110
|
-
|
111
|
-
db:exec( sql )
|
124
|
+
_G.db:exec( sql )
|
112
125
|
end
|
113
126
|
M.insertRow = insertRow
|
114
127
|
|
@@ -134,7 +147,6 @@ local updateRow = function( tableName, recordData )
|
|
134
147
|
updateStr = string.sub( updateStr, 1, #updateStr-1 )
|
135
148
|
|
136
149
|
local sql = "UPDATE " .. tableName .. " SET " .. updateStr .. " WHERE id = " .. recordData.id
|
137
|
-
print( "UPDATE SQL: " .. sql )
|
138
150
|
db:exec( sql )
|
139
151
|
end
|
140
152
|
M.updateRow = updateRow
|
@@ -153,6 +165,16 @@ local createOrUpdate = function( tableName, recordData )
|
|
153
165
|
end
|
154
166
|
M.createOrUpdate = createOrUpdate
|
155
167
|
|
168
|
+
------------------------------------------------------------------------------
|
169
|
+
-- Updates all rows in the given table
|
170
|
+
------------------------------------------------------------------------------
|
171
|
+
local updateAll = function( tablename, updateSql )
|
172
|
+
local str = "UPDATE " .. tablename ..
|
173
|
+
" SET " .. updateSql
|
174
|
+
db:exec( str )
|
175
|
+
end
|
176
|
+
M.updateAll = updateAll
|
177
|
+
|
156
178
|
------------------------------------------------------------------------------
|
157
179
|
-- Updates one column for one row in a given table
|
158
180
|
------------------------------------------------------------------------------
|
@@ -163,7 +185,6 @@ local updateAttribute = function( tablename, filter, columnName, columnValue )
|
|
163
185
|
local updateStr = "UPDATE " .. tablename ..
|
164
186
|
" SET " .. columnName .. " = " .. columnValue ..
|
165
187
|
" WHERE " .. filter
|
166
|
-
print("UPDATE SQL: " .. updateStr )
|
167
188
|
db:exec( updateStr )
|
168
189
|
end
|
169
190
|
M.updateAttribute = updateAttribute
|
@@ -185,7 +206,6 @@ local updateAttributes = function( tablename, filter, columns, columnValues )
|
|
185
206
|
updateStr = updateStr .. ", "
|
186
207
|
end
|
187
208
|
end
|
188
|
-
print("UPDATE SQL: " .. updateStr)
|
189
209
|
db:exec(
|
190
210
|
"UPDATE " .. tablename .. " SET " ..
|
191
211
|
updateStr ..
|
@@ -194,5 +214,17 @@ local updateAttributes = function( tablename, filter, columns, columnValues )
|
|
194
214
|
end
|
195
215
|
M.updateAttributes = updateAttributes
|
196
216
|
|
217
|
+
------------------------------------------------------------------------------
|
218
|
+
-- Updates all rows that match the filter in the given table
|
219
|
+
------------------------------------------------------------------------------
|
220
|
+
local updateWhere = function( tablename, updateSql, filter )
|
221
|
+
local str = "UPDATE " .. tablename ..
|
222
|
+
" SET " .. updateSql ..
|
223
|
+
" WHERE " .. filter
|
224
|
+
db:exec( str )
|
225
|
+
end
|
226
|
+
M.updateWhere = updateWhere
|
227
|
+
|
228
|
+
|
197
229
|
return M
|
198
230
|
|
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
local M = {}
|
4
4
|
|
5
|
+
local geometry = require "geometry"
|
6
|
+
M.geometry = geometry
|
7
|
+
|
5
8
|
local ioExt = require "io_ext"
|
6
9
|
M.io = ioExt
|
7
10
|
|
@@ -14,7 +17,6 @@ M.table = tableExt
|
|
14
17
|
local timeExt = require "time_ext"
|
15
18
|
M.time = timeExt
|
16
19
|
|
17
|
-
|
18
20
|
local debug = function( msg )
|
19
21
|
native.showAlert("DEBUG", msg, {"OK"})
|
20
22
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
------------------------------------------------------------------------------
|
2
|
+
-- Module for SQL generation
|
3
|
+
------------------------------------------------------------------------------
|
4
|
+
local _ = require 'underscore'
|
5
|
+
local string_ext = require 'string_ext'
|
6
|
+
|
7
|
+
local M = {}
|
8
|
+
------------------------------------------------------------------------------
|
9
|
+
-- Generate the sql for the given field def flags
|
10
|
+
------------------------------------------------------------------------------
|
11
|
+
local sqlForFieldFlags = function(fieldDef)
|
12
|
+
if fieldDef.flags ~= nil then
|
13
|
+
return _.join(fieldDef.flags, ' '):upper()
|
14
|
+
else
|
15
|
+
return ''
|
16
|
+
end
|
17
|
+
end
|
18
|
+
M.sqlForFieldFlags = sqlForFieldFlags
|
19
|
+
|
20
|
+
------------------------------------------------------------------------------
|
21
|
+
-- Generate a CREATE TABLE IF NOT EXISTS statement
|
22
|
+
-- for the given tablename and tablefield definitions
|
23
|
+
------------------------------------------------------------------------------
|
24
|
+
local generateCreateTable = function(tableName, tableFields)
|
25
|
+
local result = ''
|
26
|
+
result = 'CREATE TABLE IF NOT EXISTS ' .. tableName .. '('
|
27
|
+
for fieldName,fieldDef in pairs(tableFields) do
|
28
|
+
result = result .. string_ext.doubleQuote(fieldName) .. ' ' .. fieldDef.dataType:upper()
|
29
|
+
result = result .. ' ' .. M.sqlForFieldFlags(fieldDef)
|
30
|
+
result = result .. ','
|
31
|
+
end
|
32
|
+
result = string.sub( result, 1, result:len()-1 )
|
33
|
+
result = result .. ')'
|
34
|
+
return result
|
35
|
+
end
|
36
|
+
M.generateCreateTable = generateCreateTable
|
37
|
+
|
38
|
+
------------------------------------------------------------------------------
|
39
|
+
-- Generate a SELECT statement
|
40
|
+
--
|
41
|
+
-- Parameters:
|
42
|
+
-- tableName
|
43
|
+
-- columns
|
44
|
+
-- where
|
45
|
+
-- order
|
46
|
+
-- limit
|
47
|
+
------------------------------------------------------------------------------
|
48
|
+
local generateSelect = function(params)
|
49
|
+
local tableName = ''
|
50
|
+
if params.tableName == nil or params.tableName == '' then
|
51
|
+
return ''
|
52
|
+
else
|
53
|
+
tableName = params.tableName
|
54
|
+
end
|
55
|
+
|
56
|
+
local columns = ''
|
57
|
+
if params.columns == nil or params.columns == '' then
|
58
|
+
columns = '*'
|
59
|
+
else
|
60
|
+
columns = params.columns
|
61
|
+
end
|
62
|
+
|
63
|
+
local result = ''
|
64
|
+
result = 'SELECT ' .. columns .. ' FROM ' .. tableName
|
65
|
+
if params.where ~= nil and params.where ~= '' then
|
66
|
+
result = result .. ' WHERE ' .. params.where
|
67
|
+
end
|
68
|
+
if params.order ~= nil and params.order ~= '' then
|
69
|
+
result = result .. ' ORDER BY ' .. params.order
|
70
|
+
end
|
71
|
+
if params.limit ~= nil and params.limit ~= '' then
|
72
|
+
result = result .. ' LIMIT ' .. params.limit
|
73
|
+
end
|
74
|
+
return result
|
75
|
+
end
|
76
|
+
M.generateSelect = generateSelect
|
77
|
+
|
78
|
+
|
79
|
+
return M
|
data/lib/nakor/version.rb
CHANGED
data/nakor.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nakor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
16
|
-
requirement: &
|
16
|
+
requirement: &70127996041500 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70127996041500
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: aruba
|
27
|
-
requirement: &
|
27
|
+
requirement: &70127996040980 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70127996040980
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: cucumber
|
38
|
-
requirement: &
|
38
|
+
requirement: &70127996040480 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,21 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: metric_fu
|
49
|
-
requirement: &70361594269960 !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
|
-
requirements:
|
52
|
-
- - ! '>='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
type: :development
|
56
|
-
prerelease: false
|
57
|
-
version_requirements: *70361594269960
|
46
|
+
version_requirements: *70127996040480
|
58
47
|
- !ruby/object:Gem::Dependency
|
59
48
|
name: rspec
|
60
|
-
requirement: &
|
49
|
+
requirement: &70127996039980 !ruby/object:Gem::Requirement
|
61
50
|
none: false
|
62
51
|
requirements:
|
63
52
|
- - ! '>='
|
@@ -65,7 +54,7 @@ dependencies:
|
|
65
54
|
version: '0'
|
66
55
|
type: :development
|
67
56
|
prerelease: false
|
68
|
-
version_requirements: *
|
57
|
+
version_requirements: *70127996039980
|
69
58
|
description: ! "\n To create a new Corona SDK game using nakor, just run:\n\n nakor
|
70
59
|
generate awesome_game\n\n This will create an awesome_game directory in the current
|
71
60
|
directory, and copy all corona game template files into it.\n\n To run the generated
|
@@ -79,16 +68,20 @@ extra_rdoc_files: []
|
|
79
68
|
files:
|
80
69
|
- .gitignore
|
81
70
|
- Gemfile
|
71
|
+
- README.md
|
82
72
|
- Rakefile
|
83
73
|
- bin/nakor
|
84
74
|
- features/generate.feature
|
75
|
+
- features/step_definitions/generate_steps.rb
|
85
76
|
- features/support/setup.rb
|
77
|
+
- features/update.feature
|
86
78
|
- lib/nakor.rb
|
87
79
|
- lib/nakor/app.rb
|
88
80
|
- lib/nakor/cli.rb
|
89
81
|
- lib/nakor/generators/app.rb
|
90
82
|
- lib/nakor/generators/corona-game-template/README
|
91
83
|
- lib/nakor/generators/corona-game-template/about.lua
|
84
|
+
- lib/nakor/generators/corona-game-template/active_record.lua
|
92
85
|
- lib/nakor/generators/corona-game-template/bk_default.png
|
93
86
|
- lib/nakor/generators/corona-game-template/btn_about.png
|
94
87
|
- lib/nakor/generators/corona-game-template/btn_about_over.png
|
@@ -100,22 +93,26 @@ files:
|
|
100
93
|
- lib/nakor/generators/corona-game-template/btn_settings_over.png
|
101
94
|
- lib/nakor/generators/corona-game-template/build.settings
|
102
95
|
- lib/nakor/generators/corona-game-template/config.lua
|
96
|
+
- lib/nakor/generators/corona-game-template/geometry.lua
|
103
97
|
- lib/nakor/generators/corona-game-template/help.lua
|
104
98
|
- lib/nakor/generators/corona-game-template/init_buttons.lua
|
105
99
|
- lib/nakor/generators/corona-game-template/io_ext.lua
|
106
100
|
- lib/nakor/generators/corona-game-template/loadmenu.lua
|
107
101
|
- lib/nakor/generators/corona-game-template/main.lua
|
108
102
|
- lib/nakor/generators/corona-game-template/menu.lua
|
103
|
+
- lib/nakor/generators/corona-game-template/middleclass.lua
|
109
104
|
- lib/nakor/generators/corona-game-template/orm.lua
|
110
105
|
- lib/nakor/generators/corona-game-template/play.lua
|
111
106
|
- lib/nakor/generators/corona-game-template/radlib.lua
|
112
107
|
- lib/nakor/generators/corona-game-template/settings.lua
|
113
108
|
- lib/nakor/generators/corona-game-template/splash_screen.png
|
109
|
+
- lib/nakor/generators/corona-game-template/sql.lua
|
114
110
|
- lib/nakor/generators/corona-game-template/string_ext.lua
|
115
111
|
- lib/nakor/generators/corona-game-template/table_ext.lua
|
116
112
|
- lib/nakor/generators/corona-game-template/time_ext.lua
|
117
113
|
- lib/nakor/generators/corona-game-template/ui.lua
|
118
114
|
- lib/nakor/generators/corona-game-template/underscore.lua
|
115
|
+
- lib/nakor/utilities/update_rad_lib.rb
|
119
116
|
- lib/nakor/version.rb
|
120
117
|
- nakor.gemspec
|
121
118
|
- spec/app_spec.rb
|
@@ -139,11 +136,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
136
|
version: '0'
|
140
137
|
requirements: []
|
141
138
|
rubyforge_project: nakor
|
142
|
-
rubygems_version: 1.8.
|
139
|
+
rubygems_version: 1.8.17
|
143
140
|
signing_key:
|
144
141
|
specification_version: 3
|
145
142
|
summary: Nakor is a gem that encapsulates the corona-game-template project.
|
146
143
|
test_files:
|
147
144
|
- features/generate.feature
|
145
|
+
- features/step_definitions/generate_steps.rb
|
148
146
|
- features/support/setup.rb
|
147
|
+
- features/update.feature
|
149
148
|
- spec/app_spec.rb
|