Having problem with getPreference and setPreferences in corona - lua

I have been following the tutorials on corona website and everything has been going well so far.
But in the tutorial "Displaying and saving score" i seem to have the following runtime error.
attempt to call field setPreferences' (a nil value)
This is the code of score.lua
local M = {}
M.score = 0
function M.init( options )
local customOptions = options or {} -- nice use of "or" operator
local opt = {}
opt.fontSize = customOptions.fontSize or 24
opt.font = customOptions.font or native.systemFont
opt.x = customOptions.x or display.contentCenterX
opt.y = customOptions.y or opt.fontSize*0.5 -- such that the score is positioned at the top, half of its font size.
opt.maxDigits = customOptions.maxDigits or 6
opt.leadingZeros = customOptions.leadingZeros or false
local prefix = ""
if ( opt.leadingZeros ) then
prefix = "0"
end
M.format = "%" .. prefix .. opt.maxDigits .. "d" -- so that its accesible in other modules.
-- Create the score display object
M.scoreText = display.newText( string.format( M.format, 0 ), opt.x, opt.y, opt.font, opt.fontSize ) -- string.format() works like printf and scanf statements
M.scoreText:setFillColor(1,0,0)
return M.scoreText
end
function M.set( value )
M.score = tonumber(value)
M.scoreText.text = string.format( M.format, M.score )
end
function M.get()
return M.score
end
function M.add( amount )
M.score = M.score + tonumber(amount)
M.scoreText.text = string.format( M.format, M.score )
end
function M.save()
print (" the score is " .. M.score)
local saved = system.setPreferences( "app", { currentScore=M.score } )
if ( saved == false) then
print ( "ERROR: could not save score" )
end
end
function M.load()
local score = system.getPreference( "app", "currentScore", "number" )
if ( score ) then
return tonumber(score)
else
print( "ERROR: could not load score (score may not exist in storage)" )
end
end
return M
This is the code of main.lua
local score = require( "score" )
local scoreText = score.init(
{
fontSize = 20,
font = "CoolCustomFont.ttf",
x = display.contentCenterX,
y = 30,
maxDigits = 7,
leadingZeros = true
})
local savedScore = score.load()
score.set( 1000 ) -- Sets the score to value
score.save()
I am aware there are other ways of keeping score, but I want to know what the problem is in my code. I googled everywhere but couldn't come up with any solution. Maybe I have made a mistake somewhere that I'm not able to identify.
Even tried a build on my smart phone, but ended up getting the same error.

From corona docs
Syntax
system.setPreferences( category, preferences )
category (required)
String. Indicates which set of preferences should be accessed on the system. Currently, only the "app" category is supported — this is the application's custom preferences defined by the Corona app developer.
preferences (required)
Table. Table of preferences to be written to storage. This table should contain key-value pairs where the key is the unique name of the preference and its value is either a boolean, number, or string.
if your M.score is nil then you might get an error
try this
local saved = system.setPreferences( "app", { currentScore=M.score or 0 } )

Related

(Fivem vRP) Basic Market attempt to index a nil value (local 'gudz')

i get this error at line 94 and i dont really know how to fix this error. if someone could help fix this error it would really help me.
-- a basic market implementation
local lang = vRP.lang
local cfg = module("cfg/markets")
local market_types = cfg.market_types
local markets = cfg.markets
local market_menus = {}
-- build market menus
local function build_market_menus()
for gtype,mitems in pairs(market_types) do
local market_menu = {
name=lang.market.title({gtype}),
css={top = "75px", header_color="rgba(0,255,125,0.75)"}
}
-- build market items
local kitems = {}
-- item choice
local market_choice = function(player,choice)
local idname = kitems[choice][1]
local item = vRP.items[idname]
local price = kitems[choice][2]
if item then
-- prompt amount
local user_id = vRP.getUserId(player)
if user_id ~= nil then
vRP.prompt(player,lang.market.prompt({item.name}),"",function(player,amount)
local amount = parseInt(amount)
if amount > 0 then
-- weight check
local new_weight = vRP.getInventoryWeight(user_id)+item.weight*amount
if new_weight <= vRP.getInventoryMaxWeight(user_id) then
-- payment
if vRP.tryFullPayment(user_id,amount*price) then
vRP.giveInventoryItem(user_id,idname,amount,true)
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.paid({amount*price})}, type = "success", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.not_enough()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.inventory.full()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.common.invalid_value()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
end)
end
end
end
-- add item options
for k,v in pairs(mitems) do
local item = vRP.items[k]
if item then
kitems[item.name] = {k,math.max(v,0)} -- idname/price
market_menu[item.name] = {market_choice,lang.market.info({v,item.description.. "\n\n" ..item.weight.. " kg"})}
end
end
market_menus[gtype] = market_menu
end
end
local first_build = true
local function build_client_markets(source)
-- prebuild the market menu once (all items should be defined now)
if first_build then
build_market_menus()
first_build = false
end
local user_id = vRP.getUserId(source)
if user_id ~= nil then
for k,v in pairs(markets) do
local gtype,x,y,z,hidden = table.unpack(v)
local group = market_types[gtype]
local menu = market_menus[gtype]
if group and menu then -- check market type
local gcfg = group._config
local function market_enter()
local user_id = vRP.getUserId(source)
if user_id ~= nil and vRP.hasPermissions(user_id,gcfg.permissions or {}) then
vRP.openMenu(source,menu)
end
end
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:close()
local function adminz_open()
TriggerClientEvent("chatMessage", source, "Min bror " .. gudsp)
end
local function market_leave()
vRP.closeMenu(source)
end
if hidden == true then
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
else
vRPclient.addBlip(source,{x,y,z,gcfg.blipid,gcfg.blipcolor,lang.market.title({gtype})})
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
end
vRP.setArea(source,"vRP:adminz",153.53675842285,-255.70140075684,51.399478912354,1,1.5,adminz_open,market_leave)
end
end
end
end
AddEventHandler("vRP:playerSpawn",function(user_id, source, first_spawn)
if first_spawn then
build_client_markets(source)
end
end)
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:read() is syntactic sugar for gudz["read"](gudz).
gudz["read"] is an indexing operation. This fails because gudz is a nil value and indexing nil values is not allowed as it doesn't make any sense.
That's like referring to a book page of a book that does not exist. You won't be able to read that page anyway.
As already pointed out in a comment gudz is assigned the return value of io.open( "vfs-core.txt", "r" ) which in this case is nil.
So let's refer to the Lua Reference Manual may its wisdom enlighten us.
io.open (filename [, mode])
This function opens a file, in the mode specified in the string mode.
In case of success, it returns a new file handle.
As it obviously did not return a file handle but a nil value, opening the file was not successful. So check path and file.

Visualize Lua variables

I would like to display all the variables of Lua code using some debugger functions, but i can't get the exacte size of the tables, and also i can't retrieve the element of some tables (value, name, etc).
The following code illustrate what i did :
local name, value;
local NIL = {} -- to represent nil variables
local locals = {}
local a = 9
local i = 1
local tab ={1,2,3,4,4,4}
local tab2 = {22,22,22,22}
local tab4 = {'X', 'Y','Z'}
while( true ) do
name, value = debug.getlocal( 1, i )
if ( name == nil ) then break end
locals[ name ] = value == nil and NIL or value
i = i + 1
end
for k, v in pairs( locals ) do
if(type(v) ~= "table") then -- if it's a simple variable
print( k, v )
else
print("tabel : "..k) -- if it's a table, display it's element
print("size : "..#k)
-- I want to diplay all the elements of the table !!
for x, y in pairs(v) do
print(y)
end
end
end
you can use inspect library (useful to print nested tables) or print_r function

how to parse this data structure in corona sdk?

hello I have this json data
"bookinfo": { "result1":{"page":"1","text":"aa","audio":"1.mp3"},
"result2":{"page":"1","text":"bb","audio":"2.mp3"},
"result3":{"page":"1","text":"cc.","audio":"3.mp3"} }
and I use this code
local function networkListener( event )
if ( event.isError ) then
print ( "ERROR!" )
else
local jsonContent = json.decode(event.response).bookinfo
print(jsonContent[1].text )
end
end
json data don't have only have 3 result1,2,3 ... but hundreds, this where the difficulty come from.
My question is jsonContent[1].text don't work, how to access sub-elements without knowing their names ? just by indexing?
** note : I'm sure this is not a duplicate of any question in stackoverflow, thanks a lot.
I found a dirty workaround that at least works in my case, printing the dictionary elements get's un-ordered... so I followed this approach.
I added this function to main
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
then I used this
local count = 0
local function networkListener( event )
if (event.isError) then
print ( "ERROR!" )
else
local jsonContent = json.decode(event.response)
count = tablelength(jsonContent.bookinfo); print(count)
local content = jsonContent
local texts = {}
for i=1,count do texts[i] = jsonContent.bookinfo["result"..i].text end
end
end
if you have a better solution please let us know.

Scanning folders using lua

I'm trying to get the name of all the file saved in two folders, the name are saved as :
1.lua 2.lua 3.lua 4.lua and so on
the folders name are :
first folder : "/const/"
second folder: "/virt/"
what I'm trying to do is only get the number of the files and this works but not in the right order, when I get the 17 file for example I get the 17th delivered from the function before the 15 and this causes for me a problem here the code of the function that I'm using :
local virt_path = "/virt/"
local const_path = "/const"
local fs = require "lfs"
local const = {}
for num = 1, (numberoffile)do -- numberoffile is predfined and can't be change
const[num] = assert(
dofile (const_path .. mkfilename(num)),
"Failed to load constant ".. num ..".")
end
local function file_number() --this is the function that causes me a headach
local ci, co, num = ipairs(const)
local vi, vo, _ = fs.dir(virt_path)
local function vix(o)
local file = vi(o)
if file == nil then return nil end
local number = file:match("^(%d+).lua$")
if number == nil then return vix(o) end
return tonumber(number)
end
local function iter(o, num)
return ci(o.co, num) or vix(o.vo, num)
end
return iter, {co=co, vo=vo}, num
end
As I said the function delive the need return values but not the right Arithmetic order.
any idea what I'm doing wrong here ?
I use my path[1] library.
1 We fill table with filenames
local t = {}
for f in path.each("./*.lua", "n") do
t[#t + 1] = tonumber((path.splitext(f)))
end
table.sort(t)
for _, i in ipairs(t) do
-- do work
end
2 We check if files exists
for i = 1, math.huge do
local p = "./" .. i .. ".lua"
if not path.exists(p) then break end
-- do work
end
[1] https://github.com/moteus/lua-path

lua - checking for duplicate data in a string

I have the following string data that I receive as input:
"route1,1234,1,no~,,route2,1234,1,no~,"
It represents two "records" of data... where each record has 4 fields.
I've built code to parse this string into it's individual columns / fields.
But the part that isn't working is when I test to see if I have any duplicates in field 2. Field 2 is the one that currently has "1234" as the value.
Here's the code:
function string:split(delimiter)
local result = { }
local from = 1
local delim_from, delim_to = string.find( self, delimiter, from )
while delim_from do
table.insert( result, string.sub( self, from , delim_from-1 ) )
from = delim_to + 1
delim_from, delim_to = string.find( self, delimiter, from )
end
table.insert( result, string.sub( self, from ) )
return result
end
local check_for_duplicate_entries = function(route_data)
local route
local route_detail = {}
local result =true
local errtxt
local duplicate = false
print("received :" ..route_data)
route = string.gsub(route_data, "~,,", "~")
route = route:sub(1,string.len(route)-2)
print("route :" ..route)
-- break up in to an array
route = string.split(route,"~")
for key, value in pairs(route) do
route_detail[key] = string.split(value,",")
end
local list_of_second_column_only = {}
for key,value in pairs(route_detail) do
local temp = value[2]
print(temp .. " - is the value I'm checking for")
if list_of_second_column_only[temp] == nil then
print("i dont think it exists")
list_of_second_column_only[key] = value[2]
print(list_of_second_column_only[key])
else
--found a duplicate.
return true
end
end
return false
end
print(check_for_duplicate_entries("route1,1234,1,no~,,route2,1234,1,no~,"))
I think where I'm going wrong is the test:
if list_of_second_column_only[temp] == nil then
I think I'm checking for key with the value temp instead of a value with the value that temp contains. But I don't know how to fix the syntax.
Also, I'm wondering if there's a more efficient way to do this.
The number of "records" i receive as input is dynamic / unknown, as is the value of the second column in each record.
Thanks.
EDIT 1
The post I was trying to use as a reference is: Search for an item in a Lua list
In the answer, they show how to test for a record in the table by value, instead of looping through the entire table...
if items["orange"] then
-- do something
end
I was playing around to try and do something similar...
This should be a bit more efficient with only one table creation and less regex matching.
The match does require that you're only interested in dups in the second field.
local function check_for_duplicate_entries(route_data)
assert(type(route_data)=="string")
local field_set = {}
for route in route_data:gmatch"([^~]*)~,?,?" do
local field = route:match",([^,]*)"
if field_set[field] then
return true
else
field_set[field] = true
end
end
return false
end
Try this. It's doing the check on the value of the second field.
I haven't looked at the efficiency.
if list_of_second_column_only[value[2]] == nil then
print("i dont think it exists")
list_of_second_column_only[value[2]] = true
print(list_of_second_column_only[value[2]])
else
--found a duplicate.
return true
end

Resources