This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
TplayerJ's profile picture

[Lua][Error] attempt to compare __lt on nil and number

Started by TplayerJ, 25 November 2012 - 10:27 PM
TplayerJ #1
Posted 25 November 2012 - 11:27 PM
So I'm doing a little coding for my server and I'm currently debugging the code atm, but I have found an error I can't explain (might be because its 5 in the morning but whatever XD). So the problem occurs in this function.
Spoilerfunction convertToClock(s)
number = tonumber(s)
if number < 10 then s = ("0"..s) end
return s
end
ya…. I believe that I am giving it a valid arguement, but it is telling me no (Yes I have tried using a smaller sample of code from my main code). The full code is in this spoiler.
Spoiler

--PvP_Tarith alpha_1.0
--Developed By TplayerJ

--Variables
ffLength = 900
ffWait = 4500
sel = 1
list = {"Start Field",
        "Check Time Left",
        "Current Time"}

--Functions

--Draws the border of the screen
function drawBorder()
    for xBorder = 14,37 do
        for yBorder = 4, 13 do
            term.setCursorPos(xBorder,yBorder)
            term.write(" ")
        end
    end
    for i = 14, 37 do term.setCursorPos(i,4) term.write("*") end
    for i = 14, 37 do term.setCursorPos(i,13) term.write("*") end
    for i = 5, 12 do
        term.setCursorPos(14,i) term.write("*")
        term.setCursorPos(37,i) term.write("*")
    end
end

--runs through the list and prints them on the screen, not neat but it works(i think XD)
function selectablePrint(s, number, :D/>/>
  sLength = string.len(s)
  sLength = sLength/2
  xPos = 23-sLength
  if (not bool) then
    term.setCursorPos(xPos,number*2+5)
    term.write("- "..s)
  else
    term.setCursorPos(xPos-1, number*2+5)
    term.write("< "..s.." >")
  end   
end

--Gathers the time from an online resource and returns the values as hour, minute, month, then day
function currentTime()
    info = http.get("http://timeapi.org/utc/now")
    cDate = (info.readAll():sub(6,10))
    cTime = (info.readAll():sub(12,16))
    h = cTime:sub(1,2)
    m = cTime:sub(4,5)
    month = cDate:sub(1,2)
    day = cDate:sub(4,5)
    return h, m, month, day
end

--Problem Child
function convertToClock(s)
    number = tonumber(s)
    if number < 10 then s = ("0"..s) end
    return s
end

--followed after the selection (refer to handleKey)
function handleForce()
    untilReady = untilReady()
    if (untilReady) > ffWait then
    force(h, m, day, month)
    h, m, month, day = currentTime()
    f = fs.open("previousTime", "w")
    f.write(h..":"..m.."\n")
    f.write(month.."-"..day)
    f.close()
    else NoForce() end

end

--message made if time still remains
function NoForce()
    drawBorder()
    term.setCursorPos(22,6) term.write("Too  Soon")
    term.setCursorPos(20,8) term.write("Check  Your")
    term.setCursorPos(21,10) term.write("Time  Left")
    os.sleep(5)
end

--tries to keep the time current incase of lag or otherwise
function reTime(timeEnd)
    h, m, month, day = currentTime()
    cTime = (((((month*30)+day)*24)+h)*60)+m
    timeLeft = timeEnd - cTime
    return timeLeft
end

--returns time left until next use
function untilReady()
    drawBorder()
    f = fs.open("previousTime", "r")
    prev = f.readLine()
    prev2 = f.readLine()
    ph = prev:sub(1,2)
    pm = prev:sub(4,5)
    pmonth = prev2:sub(1,2)
    pday = prev2:sub(4,5)
    h, m, month, day = currentTime()
    full =(((((month*30)+day)*24)+h)*60)+m
    pFull = (((((pmonth*30)+day)*24)+h)*60)+m
    f.close()
    untilReady = full - pfull
    return untilReady
end

--followed after selection (refer to handleKey)
function handleTimeLeft()
    drawBorder()
    untilReady = untilReady()
    if untilReady > fwait then
        term.setCursorPos(20,7) term.write("Ready  To Be")
        term.setCursorPos(23,9) term.write("Active")
    else
        for i = 0,5 do
            hLeft = untilReady/60 -untilReady % 60
            mLeft = (untilReady%60)*60 - i
            if mLeft < 0 then
                hLeft = hLeft - 1
                mLeft = 60 - mLeft
            end
            term.setCursorPos(23,8)
            hleft = convertToCLock(hLeft)
            mLeft = convertToClock(mLeft)
            term.write(hLeft.."  "..mLeft)
            os.wait(.95)
        end
    end
end

--followed after selection (refer to handleKey)
function handleClock()
    h, m, month, day = currentTime()
    drawBorder()
    for i = 0,4 do
        m = m - i
        if m < 0 then
            m = 60 - m
            h = h - 1
        end
        h = convertToClock(h)
        m = convertToClock(m)
        month = convertToClock(month)
        day = convertToClock(day)
        term.setCursorPos(15,5) term.write("Date: "..month.."/"..day)
        term.setCursorPos(20,8) term.write(h.." : "..m.." UCT")
        os.sleep(.95)
    end
end

--activates the forcefield
function force(h, m, day, month)
    timeLeft = ffLength
    timeEnd = ((((((month*30)+day)*24)+h)*60)+m + ffLength)
    redstone.setOutput("back", true)
    while timeLeft > 0 do
        drawBorder()
        term.setCursorPos(20,7) term.write("FORCE  FIELD")
        term.setCursorPos(23,9) term.write("ACTIVE")
        if timeLeft%50==0 then
            timeLeft = reTime(timeEnd)
        end
        hloop = timeleft/60 - timeleft%60
        mloop = (timeleft%60)*60
        hloop = convertToClock(hloop)
        mloop = convertToClock(mloop)
        term.setCursorPos(23,11) term.write(hloop.."  "..mloop)   
        os.sleep(.95)
        timeLeft = timeLeft - 1
    end
    redstone.setOutput("back", false)
end

--seperates the usage of keys into different functions
function handleKey(key)
    if key == ("200" or "17") then
        if sel > 1 then sel = sel-1 end
    end
    if key == ("208" or "31") then
        if sel < #list then sel = sel+1 end
    end
    if key == 28 then
        if sel == 1 then
            handleForce()
        end
        if sel == 2 then
            handleTimeLeft()
        end
        if sel == 3 then
            handleClock()
        end
    end
end

--prints the background (prelude to problem child)
function printBack()
    for i = 0,50 do
        term.setCursorPos(i,1) term.write("-")
        term.setCursorPos(i,18) term.write("-")
    end
    for i = 0,18 do
        term.setCursorPos(1,i) term.write("|")
        term.setCursorPos(50,i) term.write("|")
    end
    term.setCursorPos(1,1) term.write("+")
    term.setCursorPos(50,1) term.write("+")
    term.setCursorPos(1,18) term.write("+")
    term.setCursorPos(50,18) term.write("+")
    h, m, month, day = currentTime()
    h = convertToClock(hnumber)
    m = convertToClock(m)
    term.setCursorPos(6,1) term.write("< "..h.." : "..m.." >")
end


--Body
if (not fs.exists("previousTime")) then
    h = fs.open("previousTime", "w")
    h.write("00:00".."\n")
    h.write("00-00")
    h.close()
end
term.clear()
while true do
    os.startTimer(15)
    printBack()
    event, param1 = os.pullEventRaw()
    if event == "key" then
        handleKey(param1)
        for i = 1,(#list) do
            if sel == i then
                ool = true
            else
                bool = false
            end
            selectablePrint(list[i], i, bool)
        end
    end
end
In case you wanted the backstory for whats going on in the code I'm putting it here
SpoilerSo we are making a pvp base that is only supposed to allow a forcefield to go off once every hour after the last 15 minute usage.
I am fairly new to splitting strings and the fs api, so the problem may be occuring there, but I'm not sure.
Any amount of criticism is greatly appreciated. The main thing though is the one error I'm getting that was posted in the title line 59:attempt to compare __lt on nil and number .
KaoS #2
Posted 25 November 2012 - 11:52 PM
tonumber returns nil if it cannot convert 's' to a number, it is clearly a string that cannot be converted…. try using this


function convertToClock(s)
  return ((tonumber(s) or 0<10) and '0' or '')..(s or 0)
end

if you want to keep your formatting:

function convertToClock(s)
number = tonumber(s) or 0
if number < 10 then s = ("0"..s) end
return s
end