How to get a variable name that is created in a for loop - sql

Basically I have a for loop that is creating variables based on data in a database, I then have an event listener that is also created based on the for loop and I want to know which text is pressed
Ive tried events in the function, creating a variable for my row.name etc.
for row in db:nrows( "SELECT * FROM Students WHERE Class = '"..class.."'" ) do
print(row.Name)
--track how many students there are
count = count+1
--When displaying the names, put them in line, if they go below 1000 y level, move to the right and go down again
ny = ny + 80
if (ny == 1000) then
nx = nx + 300
ny = 280
end
-- Display students
student[row] = display.newText( sceneGroup, row.Name, nx, ny, native.systemFont, 30 )
--Make a button for every student in the row that goes to studentscene function
student[row]:addEventListener( "tap", studentscene)
end
The function then looks like
local function studentscene()
composer.gotoScene( "student", { time=800, effect="crossFade" } )
end
I want to be able to track which student name was pressed, yet i cannot find a way to do so. I need this so I can track in the database which name it is so I can display their information

you can add it by using params in goto function
`options = {
effect = model,
time = time,
params = params,
}
composer.gotoScene( nextScene , options )`
for example do this params = {student="mohsen"}
and in scene:show function do this :
if event.params then
studen = event.params.name
end

Related

how to iterate on selected rows with datables + select extension

I use the select extension an d try to 'alert' with the id of the selected rows.
the following code fails:
let sels = jqTable.api().rows({ selected: true });
let st = '';
sels.each(function (value, index) {
st += ',' + sels.row(value).id();
});
alert(st);
The function is called once independently of selected rows:
0 row: value = [], index = 0
>=1 : value = [0, 2], index = 0
The following code succeeds:
let sels = jqTable.api().rows({ selected: true });
let st = '';
for (let i = 0; i < sels.count(); i++) {
st += ',' + sels.row(sels[0][i]).id();
}
alert(st);
what do I missunderstand with each() :
Iterate over the contents of the API result set.
I notice that the following code runs:
sels.data().each(function (value, index) {
st += ',' + value.IdFile;
});
But using it cancels the advantage of rowId : 'IdFile' in the datatable configuration.
each() is used when the dataset returns an array of results within the API objects - in the case of rows() this isn't the case - it returns a single result, which happen to be an array containing the rowIDs of the selected rows.
Your first code block fails as there's only one iteration (the results are a single array).
Your second block works, because you're iterating over that single array (sels[0]).
And your third also works, as the rows().data() does generate an array containing the data of all the selected rows.
This example will hopefully help!

Outputting data from variables in coder

I'm working in PsychoPy to design an experiment. It's almost complete, but I'm trying to output a few variables that I created in a code component into my data file for the experiment, and I haven't been able to figure out how to do that. Here is some relevant code:
if branch == 1:
if money.keys == 'left':
feedback = 'You chose $10 immediately'
TotalNow = TotalNow + 10
add = (amount - 10)/2
amount = add + amount
elif money.keys == 'right':
feedback = 'You chose $%.2f in two weeks' %(amount)
TotalLater = TotalLater + amount
TLtext = '%.2f' %(TotalLater)
amount = (amount + 10)/2
elif money.keys in ['', [], None]:
feedback = 'You did not make a choice. No reward given.'
amount = amount
if branch == 2:
if money.keys == 'right':
feedback = 'You chose $10 immediately'
TotalNow = TotalNow + 10
add = (amount - 10)/2
amount = add + amount
elif money.keys == 'left':
feedback = 'You chose $%.2f in two weeks' %(amount)
TotalLater = TotalLater + amount
TLtext = '%.2f' %(TotalLater)
amount = (amount + 10)/2
elif money.keys in ['', [], None]:
feedback = 'You did not make a choice. No reward given.'
amount = amount
I would like to output the following variables into the data file: 'TotalLater', 'TotalNow', and 'amount'. I've tried a few things, but it doesn't seem that I'm close. Any help would be appreciated.
Use the addData() method of the current experiment handler (which by default is named thisExp in Builder:
# specify each column name and its associated variable:
thisExp.addData('TotalLater', TotalLater)
thisExp.addData('TotalNow', TotalNow)
thisExp.addData('amount', amount)
Do this at the end of the relevant routine to save the current values for that trial.
If you like writing your own code, and want to learn a bit more Python, look into dictionaries which store things as "key" and "value" pairs. You start somewhere are the beginning of your program to create the dictionary with all the keys you want, and then as the program runs you store the values in the dictionary. Before the first trial you can use a function to write the keys as the column headings of a spreadsheet, and then each trial add lines with the values. For instance:
import csv ; #to use the spreadsheet export
def createDataFile(fh,d):
#fh is the handle for a file you created
#d is the name of the dictionary you have created
cdw = csv.DictWriter(fh,fieldnames = d.keys(),quoting = csv.QUOTE_MINIMAL)
cdw.writeheader()
return(cdw)
Here are some example lines from a dictionary where I am setting the values for the conditions of an expriments, note that some of these lines have keys where the value is another dictionary - the dictionaries are nested.
dty['tstX'] = dty['xoffset']['r']
dty['cbCon'] = dict(r = dty['tstCon'], l = dty['stdCon'])
dty['cbOri'] = dict(r = dty['tstStrOri'], l = dty['stdStrOri'])
dty['stdX'] = dty['xoffset']['l']
In your case you would have values for dty['amt'] = amount and at the end of a trial, you would use the function writerow() to put the latest values in their right place in the spreadsheet.
I know this is a lot more detailed, and less intuitive then the above, but you can use dictionaries in lots of places, and they are pretty darn handy.
As I have been cutting and pasting from a file of ours, the above code will likely not work out of the box for you, but will hopefully provide some useful guide posts for your own explorations.

Getting a 'nil' value when attaching an addEventListener method to a created Object

I just started getting my feet wet with Corona and trying to work with OOP. This is just a simple Match Making Game to help me along with thinking like OOP. I have 2 classes, one class will be creating an instances of a Card (i will be making multiple objects of this type of Card Class) and the other is the MatchCardsManager Class - this creates the cards and applies the properties
The error I am getting is, after i have created the object "MatchCard" i tried to apply an "addEventListener" to the object. but when i do i receive an error of the following
Support/Outlaw/Sandbox/5/MatchCardsManager.lua:53:
attempt to call method 'addEventListener' (a nil value)
stack traceback:
If i comment out the info on addEventListener, all objects are displayed accordingly to the constructor i created in MatchCard Class.
Below are my files - the error i am getting is in the MatchCardsManager class
mCard[i] = MatchCardsManager:displayPlacementCard(i, temp, x, y)
mCard[i]:addEventListener("touch", myTouch)
Any help or suggestions about fixing this or better approach would be greatly appreciated. Thank you.
The MatchCard Class will be just a simple constructor for now as this is not my issue
-- MatchCard Class
-- Meta Data
local sceneGroup = sceneGroup
local MatchCard = { }
local MatchCard_mt = { __index = MatchCard } -- metatable
------------------------------------------------
-- PRIVATE FUNCTION
------------------------------------------------
------------------------------------------------
-- PUBLIC FUNCTION
------------------------------------------------
-- constructor
function MatchCard.new (id, animal, state, imageId, x, y)
local newMCard = display.newRoundedRect( x, y, 59, 47, 5)
newMCard.strokeWidth = 3
newMCard:setFillColor( 0.5 )
newMCard:setStrokeColor( 1, 0, 0 )
newMCard.properties = {
id = id or nil,
animal = animal or nil,
state = state or 0,
imageId = imageId,
}
return setmetatable ( newMCard, MatchCard_mt )
end
MatchCardsManager Class is there I plan to create an many instances of cards
-- require files
local MatchCard = require('MatchCard') --MatchCard
local sceneGroup = sceneGroup
local MatchCardsManager = {} -- originally we should use a displayGroup
-- TODO: insert group into scene
local animalPicsReference = { "dog", "dog", "cat", "cat", "pig", "pig" , "fish", "fish"}
-- manager class properties
MatchCardsManager.totalCards = 8
MatchCardsManager.totalPairs = 4
MatchCardsManager.pairsFound = 0
MatchCardsManager.firstCardSelected = 0
MatchCardsManager.secondCardSelected = 0
-- lets create 6 MatchCardFiles
function MatchCardsManager:create()
local animalPics = animalPicsReference
local x = 108 - 85
local y = 125
print("do we go here never works")
local mCard = {}
for i=1, 4
do
x = x + 85
num = math.random(1, #animalPics)
temp = animalPics[num]
table.remove(animalPics, num)
mCard[i] = MatchCardsManager:displayPlacementCard(i, temp, x, y)
mCard[i]:addEventListener("touch", myTouch)
end
x = 108 - 85
y = 195
for j = 5, 8 do
x = x + 85
num = math.random(1, #animalPics)
temp = animalPics[num]
table.remove(animalPics, num)
mCard[j] = MatchCardsManager:displayPlacementCard(j, temp, x, y)
print(type(mCard[j]))
mCard[j]:addEventListener("touch", myTouch)
end
--mCards:addEventListener("touch", myTouch)
return mCard
end
local function myTouch( event )
if event.phase == "began" then
print( "You touched the object! "..event.target.imageId)
end
end
function MatchCardsManager:displayPlacementCard(idx, animal, x, y)
-- randomly place the cards in the object id
local card = MatchCard.new(idx, animal, 0, animal, x, y)
--card:show(x,y) -- displays card and that is it
print("animal added is "..card.properties.imageId)
return card
end
return MatchCardsManager
The problem is in the constructor.
local newMCard = display.newRoundedRect(...)
creates a display object, but the line:
return setmetatable(newMCard, MatchCard_mt)
overwrites the metatable that the display object had and so it no longer has access to display's __index metamethod that is used to find addEventListener.
To fix this, you need to look into how inheritance is added in Lua.
See Inheritance Tutorial so you can inherit addEventListener. The solution will be something like: setmetatable(MatchCard, {__index=ShapeObject}) or =display.ShapeObject}---I can't be sure how Corona implements its classes.

lua:How to use value from table 'A', in table 'B', which nested in table 'A'

In real project, TEST_TABLE would contain much of TEST_TABLE_NESTED, each with its own testVariable and bunch of testScript. test function from testScript would be used in C++ code, and TEST_TABLE_NESTED tables would be added automatically from C++ code too.
TEST_TABLE =
{
TEST_TABLE_NESTED =
{
testVariable = 5,
testScript =
{
test = function()
print(testVariable, "hello") --How to access 'testVariable'?
end
}
}
}
EDIT :
This is the actual scenario of using this script:
GameObjectScriptTables =
{
GameObject_1 = --Container of scripts corresponding to some gameObject
{
gameObjectOwner = actual_object_passed_from_c++, --This is an actual object passed from c++
GameObjectScript_1 = --This is a script with update(dt) method which will be called somwhere in c++ code
{
update = function(dt)
--here I want to use some data from gameObjectOwner like position or velocity
end
}
}
GameObject_2 =
{
gameObjectOwner = actual_object_passed_from_c++,
GameObjectScript_1 =
{
update = function(dt)
--here I want to use some data from gameObjectOwner like position or velocity
end
},
GameObjectScript_2 =
{
update = function(dt)
--here I want to use some data from gameObjectOwner like position or velocity
end
}
}
--And so on
}
Idea is that exists some testVariable object (passed from C++), which data is used all over TEST_TABLE_NESTED. For me, above example looks natural for this task, but it prints nil instead of 5. So how to acces a testVariable from testScript without printing a full path like TEST_TABLE.TEST_TABLE_NESTED.testVariable?
You're asking for something like a "parent" pointer, which tells table B about table A, but that doesn't exist. Internally, the only association they have is that one of A's values happens to be B, but any number of tables could contain B as a value. Which is B's parent?
If you want B to know about A, you'll need to tell it. You can add an extra parameter to update which receives the game owner object, or update can be a closure which contains the game owner as a bound variable, so on and so forth.
I made it work by providing a gameObjectOwner instance for each GameObjectScript_N. However I don't know is it expensive solution or not.

Lua OOP grid class with event

I'm learning lua and i'm trying the OOP approach.
To start, I'm trying to make a grid class, but I think i'm still lacking some knowledge to make it do what I want it to do.
This is my code so far:
local screen = require( 'data.screen')
Grid = {}
Grid_mt = { __index = Grid }
--- Constructs a new Grid object.
function Grid:new( params )
local self = {}
local function try( self, event )
print(self.empty)
end
for i = 1, screen.tilesAcross do
if not self[i] then
self[i] = {};
end
for j = 1, screen.tilesDown do
self[i][j] = display.newImageRect( params.group, "images/playable.png", screen.tileWidth, screen.tileHeight )
self[i][j].x = (j - 1) * (screen.tileWidth + screen.tileSpacing) + screen.leftSpacing
self[i][j].y = (i - 1) * (screen.tileHeight + screen.tileSpacing) + screen.topSpacing
self[i][j]._x = i
self[i][j]._y = j
self[i][j].enable = false
self[i][j].empty = true
self[i][j].tap = try
self[i][j]:addEventListener( "tap", self[i][j] )
end
end
setmetatable( self, Grid_mt )
return self
end
function Grid:setEnable(value, x, y)
if value ~= true and value ~= false then
error("Boolean expected")
end
self[x][y].enable = value
end
function Grid:getEnable(x, y)
return self[x][y].enable
end
function Grid:setEmpty(value, x, y)
if value ~= true and value ~= false then
error("Boolean expected")
end
self[x][y].empty = value
end
function Grid:getEmpty(x, y)
return self[x][y].empty
end
function Grid:SetmColor()
self[1][4]:setFillColor( 255,255 )
end
I have 2 questions:
My event works but I would like to do something like: print(self:getEmpty() )
but whenever I try to use a method in my event, it doesn't work "attempt to call method 'getEmpty' (a nil value)"
and also the setfillcolor wwon't work, I want to be able to change the color of a case with it.
Thanks for your time!
and if i'm going to the wrong road, let me know, and by the way, I have a working code without make a class, this is just for training purpose :)
Thnaks!
The issue is that self[i][j] is not a Grid, only self is a Grid. So when the event handler is called, self in the handler is the display object, not the Grid object. If the handler needs to know the grid object, you could assign the grid to each display object:
self[i][j].grid = self
then in try you could do
grid = self.grid
But in this case you may get a cleaner design if you have the tap handler not be specific to each display object. In this case you would use an upvalue, you can just use self:
function Grid:new( params )
local self = {}
local function try( event ) -- omit the first param, self is an upvalue
print(self.empty)
end
for i = 1, screen.tilesAcross do
...
for j = 1, screen.tilesDown do
self[i][j] = display.newImageRect( ... )
...
self[i][j]:addEventListener( "tap", try )
end
end
Since listener given is a function rather than a table, it gets only one parameter, the event, and self is an upvalue so it will be the Grid instance created just above the try function.
For the first question, more information would be needed. See my comment above.
As for the setFillColor not working, the following is taken from the Corona docs:
object:setFillColor( gray )
object:setFillColor( gray, alpha )
object:setFillColor( red, green, blue )
object:setFillColor( red, green, blue, alpha )
object:setFillColor( gradient )
gray, red, green, blue, alpha (optional)
Numbers between 0 and 1 that represent the corresponding
value for that channel. alpha represents the opacity of the object.
Now, when you are trying to execute:
self[1][4]:setFillColor( 255,255 )
you are passing the values for gray and alpha channels. The values NEED TO BE less than, or equal to 1. Probably you want to pass 1 (as 255 is generally the max. value)