My birthday is coming up, and I want to make a cake making game to celebrate it.
I'm trying to make admin for it, but it won't return as a string, it returns as nil.
I'm trying to take a substring between other substrings.
Here is my code:
local biradmin = {}
BirthdayBoy = 6
Brother = 5
AdminLeader = 4
Admin = 3
Winner = 2
VIP = 1
NonAdmin = 0
local function check(num, cmd, prefix, output, paramlist)
if output == "award" then
biradmin.getParams(1, cmd, prefix, output, paramlist)
print(output)
elseif output == "take" or output == "hold" or output == "theforce" or output == "detain" then
biradmin.getParams(1, cmd, prefix, output, paramlist)
if output == nil then
print('nil')
else
print(output)
end
else
if output == nil then
print('nil')
biradmin.getParams(1, cmd, prefix, output, paramlist)
else
print(output)
end
end
end
local function getParams(num, cmd, prefix, output, paramlist)
if num == 1 then
local param1 = string.match(cmd, prefix..output..' (.*)')
paramlist = param1
if not paramlist == nil then
print('param list identified')
else
print('nil param list')
end
end
end
function biradmin.getArgs(cmd, prefix, output, paramlist)
local findcheck = prefix
output = string.match(cmd, findcheck.."(.*)")
print(output)
check(1, cmd, prefix, output, paramlist)
end
return biradmin
I am running this code through a script. The output I keep getting is:
nil
nil
Related
I am trying to create a maze generation script using the module listed below. I'm having this strange problem were the grid variable has a value, but when return grid is called, it returns and empty table? Here is the code to the module script.
local ServerStorage = game:GetService("ServerStorage")
local cellTemplate = ServerStorage:WaitForChild("Cell")
local Maze = {}
local cellObject = {}
local grid = {}
Maze.Size = 25
Maze.CellWidth = 9
Maze.CellLength = 9
Maze.Offset = Vector3.new(0,0,0)
function Maze.new(x,z) -- Create a new cell
local newCell = {}
setmetatable(newCell,{ -- Allows us to create functions for a cell easier
__index = cellObject
})
newCell.X = math.clamp(x,1,Maze.Size)
newCell.Z = math.clamp(z,1,Maze.Size)
newCell.Visited = false
newCell.Model = cellTemplate:Clone()
newCell.Base = newCell.Model:WaitForChild("Base")
newCell.Model.Name = newCell.Model.Name.. "_".. newCell.X.. "-".. newCell.Z
newCell.Walls = {
["Forward"] = newCell.Model:WaitForChild("Forward");
["Backward"] = newCell.Model:WaitForChild("Backward");
["Left"] = newCell.Model:WaitForChild("Left");
["Right"] = newCell.Model:WaitForChild("Right");
}
if not grid[x] then grid[x] = {} end -- We might not have anything on that x axis yet; inserts it into the table
grid[x][z] = newCell
print(grid)
return newCell
end
function Maze.RenderAll() -- Render every cell; exists for more readibility
for _,cellRow in pairs(grid) do -- Loop through every cell row
for _,cell in pairs(cellRow) do -- Loop through every cell in the row
cell:Render() -- Render the cell
end
end
end
function Maze.Grid() -- Allows other scripts to get the grid but not modify it
return grid
end
function Maze.FilterUnvisited(cells) -- Takes in a table and returns one with only the cells in the table that are unvisited
local unvisited = {}
for _,cell in pairs(cells) do -- Loop through every cell in the table passed
if not cell.Visitied then -- The cell hasn't been visited
table.insert(unvisited,cell)
end
end
return unvisited
end
function Maze.GetCell(x,z)
local cell
if grid[x] and grid[x][z] then
cell = grid[x][z]
else
cell = nil
end
return cell
end
function cellObject:Render() -- Render the cell
self.Model:SetPrimaryPartCFrame(CFrame.new(Vector3.new(self.X * Maze.CellLength,0,self.Z * Maze.CellWidth) + Maze.Offset)) -- Move the cell to the correct position
if self.Visited then -- We have gone through the cell
self.Model.PrimaryPart.Color3 = Color3.new(0,1,0) -- Show that the cell has been visited; used for debugging
end
self.Model.Parent = workspace
end
function cellObject:Neighbours() -- Returns the cell's neigbours
local neighbours = {}
-- Order: Right Left Up Down
if grid[self.X + 1] and grid[self.X + 1][self.Z] then -- A cell with +1 X exists
table.insert(neighbours,grid[self.X + 1][self.Z])
end
if grid[self.X - 1] and grid[self.X - 1][self.Z] then -- A cell with -1 X exists
table.insert(neighbours,grid[self.X - 1][self.Z])
end
if grid[self.X][self.Z + 1] then -- A cell with +1 Z exists
table.insert(neighbours,grid[self.X][self.Z + 1])
end
if grid[self.X][self.Z - 1] then -- A cell with -1 Z exists
table.insert(neighbours,grid[self.X][self.Z - 1])
end
return neighbours
end
function cellObject:RandomNeighbour()
local neighbours = self:Neighbours() -- Gets the neigbours of the current cell
if #neighbours > 0 then
return neighbours[math.random(1,#neighbours)] -- Returns a random neigbour
else
return nil
end
end
function cellObject:WallArray() -- Returns an array of the walls instead of a table
local wallArray = {}
wallArray[1] = self.Walls.Forward
wallArray[2] = self.Walls.Right
wallArray[3] = self.Walls.Left
wallArray[4] = self.Walls.Backward
return wallArray
end
function cellObject:Join(cell) -- Joins 2 cells together
local wallPosition = self.Base.Position:Lerp(cell.Base.Position,.5) -- This will return the position of the wall (excluding the Y)
local cell1Array = self:WallArray()
local cell2Array = cell:WallArray()
for wallIndex,wall in pairs(cell1Array) do
if wall.Position.X == wallPosition.X and wall.Position.Z == wallPosition.Z then -- Its the right wall
wall.Transparency = 1
wall.CanCollide = false
cell2Array[4 - (wallIndex - 1)].Transparency = 1
cell2Array[4 - (wallIndex - 1)].CanCollide = false
break -- We don't need to loop anymore, since we've already removed the walls
end
end
end
function cellObject:Unjoin(cell) -- Unjoins 2 cells
local wallPosition = self.Base.Position:Lerp(cell.Base.Position,.5) -- This will return the position of the wall (excluding the Y)
local cell1Array = self:WallArray()
local cell2Array = cell:WallArray()
for wallIndex,wall in pairs(cell1Array) do
if wall.Position.X == wallPosition.X and wall.Position.Z == wallPosition.Z then -- Its the right wall
wall.Transparency = 0
wall.CanCollide = true
cell2Array[4 - (wallIndex - 1)].Transparency = 0
cell2Array[4 - (wallIndex - 1)].CanCollide = true
break -- We don't need to loop anymore, since we've already added the walls
end
end
end
return Maze
Below is the piece of code I'm having diffuculty with.
function Maze.Grid() -- Allows other scripts to get the grid but not modify it
return grid
end
I have tested printing the grid variable and it's not {} but when I call the function in the script below, I always get {}! I have no idea why this is.
Is this a bug in roblox or am I being stupid?
local ServerScriptService = game:GetService("ServerScriptService")
local Maze = require(ServerScriptService:WaitForChild("Maze"))
local latestX = 0
local latestZ = 0
function CreatePath(cell)
local nextCell = cell:RandomNextCell(false)
if nextCell then -- We have a cell next to the current one
print("Joining cells:",cell,nextCell)
cell:Join(nextCell)
cell.Visited = true
cell:Render()
wait(.01)
CreatePath(nextCell)
else -- It must be the end of the maze
print("Path generated!")
print("Maze end: ".. cell.Model.Name)
cell.Base.Color = Color3.new(1,0,0)
end
end
function GenerateMaze()
local cell = Maze.new(latestX + 1,latestZ + 1) -- Create a new cell
cell:Render() -- Render it
print("Created cell")
latestZ += 1
if latestZ > Maze.Size then -- It has exceeded the max size, move on to a new row
latestX += 1
latestZ = 0
end
if #Maze.Grid() < Maze.Size ^ 2 then
wait(.01)
GenerateMaze()
else
print("Grid completed, generating path...")
CreatePath(Maze.GetCell(1,1))
end
end
GenerateMaze()
You are returning a cached value, or well i don't find out other reason.
You may do (and it's not editable):
function Maze.Grid(i, l)
local passed = 1
local response = {}
for index, v in pairs(grid) do
response[index] = i and passed >= i and l and passed <= l and v or not (i or l) and v
-- basically get more than `i` if it, and minor than `l` if it passed
i = i + 1
end
return response
end
It should work, I don't tested it sorry.
I have the following input file
system info com1 command set
system info com2 command set
system command set1 information description test
system command 21-22 information description pass
system command T1-T2-T3 information description file
system command commonset information description info
and the following command
awk '/system command/&&/information description/ { gsub("\"","") ; print ++ OFS") Command = " $3}' inputfile.txt
gives me the following output
1) Command = set1
2) Command = 21-22
3) Command = T1-T2-T3
4) Command = commonset
Is there a way that my commands list count is not with simple numbers but with sort ordinal numbers
and to have an output like this
1st) Command = set1
2nd) Command = 21-22
3rd) Command = T1-T2-T3
4th) Command = commonset
There is no built function to get that ordinal. We need to get our hands dirty and write this code:
awk 'function ordinal(i, mod, str) {mod = i%10; str=i; if (i~/1[1-3]$/) str=str "th"; else if (mod==1) str=str "st"; else if (mod==2) str=str "nd"; else if (mod==3) str=str "rd"; else str=str "th"; return str;} /system command/&&/information description/ { gsub(/"/,"") ; print ordinal(++i) ") Command = " $3}' file
1st) Command = set1
2nd) Command = 21-22
3rd) Command = T1-T2-T3
4th) Command = commonset
Expanded form:
awk '
function ordinal(i, mod, str) {
mod = i%10
str = i
if (i~/1[1-3]$/) # for numbers ending in 11, 12, 13
str = str "th"
else if (mod==1)
str = str "st"
else if (mod==2)
str = str "nd"
else if (mod==3)
str = str "rd"
else
str = str "th"
return str
}
/system command/&&/information description/ {
gsub(/"/,"")
print ordinal(++i) ") Command = " $3
}' file
An alternative way to implement the above function would be:
function ordinal(num, idx, sfxs) {
split("st nd rd th",sfxs," ")
idx = ( (num ~ /[123]$/) && (num !~ /1[123]$/) ? num % 10 : 4 )
return num sfxs[idx]
}
I have two tables in lua (In production, a has 18 elements and b has 8):
local a = {1,2,3,4,5,6}
local b = {3,5,7,8,9}
I need to return 'a' omitting any common elements from 'b' -- {1,2,4,6} similar to the ruby command a-b (if a and b were arrays).
The best lua logic I have been able to come up with is:
local function find(a, tbl)
for _,a_ in ipairs(tbl) do if a_==a then return true end end
end
function difference(a, b)
local ret = {}
for _,a_ in ipairs(a) do
if not find(a_,b) then table.insert(ret, a_) end
end
return ret
end
local a = {1,2,3,4,5,6}
local b = {3,5,7,8,9}
local temp = {}
temp = difference(a,b)
print(temp[1],temp[2],temp[3],temp[4])
I need to loop through these table comparison pretty quick (min 10K times a second in production). Is there a cleaner way to do this?
======
This is part of a redis server side script and I have to protect my Redis CPU. Outside of a clean Lua process I have two other options:
1.Create two redis temp keys then run sinter for a big(O) of 42
18 sadd(a)
8 sadd(b)
16 sinter(a,b)
2.Return both a and b to ruby do the array comparison and send back the result.
Network cost of the back and fourth of a few thousand connections a second will be a drain on resources.
Try this:
function difference(a, b)
local aa = {}
for k,v in pairs(a) do aa[v]=true end
for k,v in pairs(b) do aa[v]=nil end
local ret = {}
local n = 0
for k,v in pairs(a) do
if aa[v] then n=n+1 ret[n]=v end
end
return ret
end
You could do this (not tested):
function difference(a, b)
local ai = {}
local r = {}
for k,v in pairs(a) do r[k] = v; ai[v]=true end
for k,v in pairs(b) do
if ai[v]~=nil then r[k] = nil end
end
return r
end
If you can modify a then it is even shorter:
function remove(a, b)
local ai = {}
for k,v in pairs(a) do ai[v]=true end
for k,v in pairs(b) do
if ai[v]~=nil then a[k] = nil end
return r
end
If your tables are sorted you could also do a parallel sweep of the two tables together, something like the following pseudo code:
function diff(a, b)
Item = front of a
Diff = front of b
While Item and Diff
If Item < Diff then
Item is next of a
Else if Item == Diff then
remove Item from a
Item = next of a
Diff = next of b
Else # else Item > Diff
Diff = next of b
This doesn't use any extra tables. Even if you want new table instead of in-place diff, only one new table. I wonder how it would compare to the hash table method (remove).
Note that it doesn't matter how many times you loop, if a and b are small then there will be no major difference between these and your alg. You'll need at least 100 items in a and in b, maybe even 1000.
Maybe something like that:
function get_diff (t1, t2)
local diff = {}
local bool = false
for i, v in pairs (t1) do
if t2 and type (v) == "table" then
local deep_diff = get_diff (t1[i], t2[i])
if deep_diff then
diff[i] = deep_diff
bool = true
end
elseif t2 then
if not (t1[i] == t2[i]) then
diff[i] = t1[i] .. ' -- not [' .. t2[i] .. ']'
bool = true
end
else
diff[i] = t1[i]
bool = true
end
end
if bool then
return diff
end
end
local t1 = {1, 2, 3, {1, 2, 3}}
local t2 = {1, 2, 3, {1, 2, 4}}
local diff = get_diff (t1, t2)
Result:
diff = {
nil,
nil,
nil,
{
[3] = "3 -- not [4]"
}
}
This question already has answers here:
method for serializing lua tables
(5 answers)
Closed 8 years ago.
I would like to serialize a table so that I can insert it into a database and retrieve it later on. How would I do this?
maybe like this https://gist.github.com/rangercyh/5814003
local szStr = ""
function print_lua_table (lua_table, indent)
indent = indent or 0
for k, v in pairs(lua_table) do
if type(k) == "string" then
k = string.format("%q", k)
end
local szSuffix = ""
if type(v) == "table" then
szSuffix = "{"
end
local szPrefix = string.rep(" ", indent)
formatting = szPrefix.."["..k.."]".." = "..szSuffix
if type(v) == "table" then
szStr = szStr..formatting
print_lua_table(v, indent + 1)
szStr = szStr..szPrefix.."},"
else
local szValue = ""
if type(v) == "string" then
szValue = string.format("%q", v)
else
szValue = tostring(v)
end
szStr = szStr..formatting..szValue..","
end
end
end
How to serialize Lua value nicely?
local serialize
do
local num_fmt = '%.17g'
local NaN_serialized = { -- This idea was stolen from lua-nucleo
[num_fmt:format(1/0)] = '1/0',
[num_fmt:format(-1/0)] = '-1/0',
[num_fmt:format(0/0)] = '0/0'
}
local function serialize_table(t, indent)
indent = indent or ''
local new_indent = indent..'\t'
if next(t) == nil then
return '{}'
else
local lines = {}
local function add_line(key)
local ser_key = key
if type(key) ~= 'string' or not key:find'^[%a_][%w_]*$' then
ser_key = '['..serialize(key, new_indent)..']'
end
table.insert(lines,
ser_key..' = '..serialize(t[key], new_indent))
end
local other_keys = {}
local keys = setmetatable({number = {}, string = {}},
{__index = function() return other_keys end})
for k in pairs(t) do
table.insert(keys[type(k)], k)
end
table.sort(keys.number)
table.sort(keys.string)
for _, k in ipairs(keys.number) do
add_line(k)
end
for _, k in ipairs(keys.string) do
add_line(k)
end
for _, k in ipairs(other_keys) do
add_line(k)
end
return '{\n'..new_indent..table.concat(lines, ',\n'..new_indent)
..'\n'..indent..'}'
end
end
function serialize(v, indent)
if type(v) == 'string' then
return ('%q'):format(v)
elseif type(v) == 'boolean' then
return tostring(v)
elseif type(v) == 'nil' then
return tostring(v)
elseif type(v) == 'number' then
return (num_fmt:format(v):gsub('^.*', NaN_serialized))
elseif type(v) == 'table' then
return serialize_table(v, indent)
else
error('Can not serialize '..type(v))
end
end
end
-- What it can:
print(serialize(math.huge))
print(serialize'"What\'s up?"\n\t123')
print(serialize{{}, {{}}})
-- And what it can not:
local t = {}
local tt = {[t] = t}
print(serialize(tt)) -- tt is not a tree, so it was serialized incorrectly
I am wanting to convert a 2d lua table into a string, then after converting it to a string convert it back into a table using that newly created string. It seems as if this process is called serialization, and is discussed in the below url, yet I am having a difficult time understanding the code and was hoping someone here had a simple table.toString and table.fromString function
http://lua-users.org/wiki/TableSerialization
I am using the following code in order to serialize tables:
function serializeTable(val, name, skipnewlines, depth)
skipnewlines = skipnewlines or false
depth = depth or 0
local tmp = string.rep(" ", depth)
if name then tmp = tmp .. name .. " = " end
if type(val) == "table" then
tmp = tmp .. "{" .. (not skipnewlines and "\n" or "")
for k, v in pairs(val) do
tmp = tmp .. serializeTable(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and "\n" or "")
end
tmp = tmp .. string.rep(" ", depth) .. "}"
elseif type(val) == "number" then
tmp = tmp .. tostring(val)
elseif type(val) == "string" then
tmp = tmp .. string.format("%q", val)
elseif type(val) == "boolean" then
tmp = tmp .. (val and "true" or "false")
else
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
end
return tmp
end
the code created can then be executed using loadstring(): http://www.lua.org/manual/5.1/manual.html#pdf-loadstring if you have passed an argument to 'name' parameter (or append it afterwards):
s = serializeTable({a = "foo", b = {c = 123, d = "foo"}})
print(s)
a = loadstring(s)()
The code lhf posted is a much simpler code example than anything from the page you linked, so hopefully you can understand it better. Adapting it to output a string instead of printing the output looks like:
t = {
{11,12,13},
{21,22,23},
}
local s = {"return {"}
for i=1,#t do
s[#s+1] = "{"
for j=1,#t[i] do
s[#s+1] = t[i][j]
s[#s+1] = ","
end
s[#s+1] = "},"
end
s[#s+1] = "}"
s = table.concat(s)
print(s)
The general idea with serialization is to take all the bits of data from some data structure like a table, and then loop through that data structure while building up a string that has all of those bits of data along with formatting characters.
How about a JSON module? That way you have also a better exchangeable data. I usually prefer dkjson, which also supports utf-8, where cmjjson won't.
Under the kong works this
local cjson = require "cjson"
kong.log.debug(cjson.encode(some_table))
Out of the kong should be installed package lua-cjson https://github.com/openresty/lua-cjson/
Here is a simple program which assumes your table contains numbers only. It outputs Lua code that can be loaded back with loadstring()(). Adapt it to output to a string instead of printing it out. Hint: redefine print to collect the output into a table and then at the end turn the output table into a string with table.concat.
t = {
{11,12,13},
{21,22,23},
}
print"return {"
for i=1,#t do
print"{"
for j=1,#t[i] do
print(t[i][j],",")
end
print"},"
end
print"}"
Assuming that:
You don't have loops (table a referencing table b and b referencing a)
Your tables are pure arrays (all keys are consecutive positive integers, starting on 1)
Your values are integers only (no strings, etc)
Then a recursive solution is easy to implement:
function serialize(t)
local serializedValues = {}
local value, serializedValue
for i=1,#t do
value = t[i]
serializedValue = type(value)=='table' and serialize(value) or value
table.insert(serializedValues, serializedValue)
end
return string.format("{ %s }", table.concat(serializedValues, ', ') )
end
Prepend the string resulting from this function with a return, store it on a .lua file:
-- myfile.lua
return { { 1, 2, 3 }, { 4, 5, 6 } }
You can just use dofile to get the table back.
t = dofile 'myfile.lua'
Notes:
If you have loops, then you will have
to handle them explicitly - usually with an extra table to "keep track" of repetitions
If you don't have pure arrays, then
you will have to parse t differently,
as well as handle the way the keys are rendered (are they strings? are they other tables? etc).
If you have more than just integers
and subtables, then calculating
serializedValue will be more
complex.
Regards!
I have shorter code to convert table to string but not reverse
function compileTable(table)
local index = 1
local holder = "{"
while true do
if type(table[index]) == "function" then
index = index + 1
elseif type(table[index]) == "table" then
holder = holder..compileTable(table[index])
elseif type(table[index]) == "number" then
holder = holder..tostring(table[index])
elseif type(table[index]) == "string" then
holder = holder.."\""..table[index].."\""
elseif table[index] == nil then
holder = holder.."nil"
elseif type(table[index]) == "boolean" then
holder = holder..(table[index] and "true" or "false")
end
if index + 1 > #table then
break
end
holder = holder..","
index = index + 1
end
return holder.."}"
end
if you want change the name just search all compileTable change it to you preferred name because this function will call it self if it detect nested table but escape sequence I don't know if it work
if you use this to create a lua executable file that output the table it will ge compilation error if you put new line and " sequence
this method is more memory efficient
Note:
Function not supported
User data I don't know
My solution:
local nl = string.char(10) -- newline
function serialize_list (tabl, indent)
indent = indent and (indent.." ") or ""
local str = ''
str = str .. indent.."{"
for key, value in pairs (tabl) do
local pr = (type(key)=="string") and ('["'..key..'"]=') or ""
if type (value) == "table" then
str = str..nl..pr..serialize_list (value, indent)..','
elseif type (value) == "string" then
str = str..nl..indent..pr..'"'..tostring(value)..'",'
else
str = str..nl..indent..pr..tostring(value)..','
end
end
str = str:sub(1, #str-1) -- remove last symbol
str = str..nl..indent.."}"
return str
end
local str = serialize_list(tables)
print('return '..nl..str)