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

I need help with the fs API

Started by Cranium, 07 August 2012 - 02:53 PM
Cranium #1
Posted 07 August 2012 - 04:53 PM
I would like to be able to save the state of a bundled cable output, but before I go al willy nilly with adding functions here and there, and changing my already awesome program, I just need some help with the fs API.
My program is supposed to be a master control, and I need the status of all of my outpus saved to a file for switching between programs without changing the state(I have a reactor on it, and don't want to blow up). I read the fs API wiki, and I think I have what I want, but I want to run it by the Pros first, before messing everything up. Here is my saveState function:

function saveState()
local save = fs.open("status","w")
  save.writeLine("..rcstat()..")
  save.writeLine("..coolstat()..")
  save.close()
end
The output should be two lines, where either rcstat() or coolstat() should return on, off or unknown, depending on the output. Did I write it correctly, or is it going to mess up right away?
Noodle #2
Posted 07 August 2012 - 05:33 PM
function saveState()
local save = fs.open("status", "w")
save.writeLine(rcstat()) -- Rcstat is a function right?
save.writeLine(coolstat()) -- Cool stat is a function right?
save.close()
end
Untested, IDK if it'll work. I'm having troubles with figuring out the writeLine.
Are those two functions?
Cranium #3
Posted 07 August 2012 - 05:46 PM
Yeah, sorry. I have the rcstat() and coolstat() as functions that output either on, off or unknown whether that color is outputting a signal. Here they are:

function coolstat()
if (colors.test(rs.getBundledOutput("back"), colors.blue)) == true then
   write(" Off")
elseif (colors.test(rs.getBundledOutput("back"), colors.blue)) == false then
   write(" On")
else
   write(" Unknown")
end
end
function rcstat()
if (colors.test(rs.getBundledOutput("back"), colors.red)) == true then
   write(" Off")
elseif (colors.test(rs.getBundledOutput("back"), colors.red)) == false then
   write(" On")
else
   write(" Unknown")
end
end
Ponder #4
Posted 07 August 2012 - 06:22 PM
Two problem, first your code in saveState does not actually calls your two other functions. "..coolstat().." is just that, a string with "coolstat()" written in the middle. To actually call them and put periods around their output you need something like:

save.writeLine (".." .. coolstat () .. "..")
Second, your two functions don't return anything. write () is what it says on the tin, it writes its argument to the terminal. You don't want that, you want the function to return a string, so that saveState can write those strings to your save file. Therefor, your code should more look like:

function coolstat()
if (colors.test(rs.getBundledOutput("back"), colors.blue)) == true then
   return " Off"
elseif (colors.test(rs.getBundledOutput("back"), colors.blue)) == false then
   return " On"
else
   return " Unknown"
end
end
Cranium #5
Posted 07 August 2012 - 06:35 PM
Ok, so since I use that same function for other parts of the code, it would probably be easier to declare a new variable like this:

cool = colors.test(rs.getBundledOutput("back"), colors.blue)
rc = colors.test(rs.getBundledOutput("back"), colors.red)
Right? And then I can pretty much do the same for everything else?
I would just call back to that variable like this:

function saveState()
local save = fs.open("status","w")
  save.writeLine("..rc..")
  save.writeLine("..cool..")
  save.close()
end
If so, then the only thing I think I might have messed up on, is the concatenation. (the two periods(..), for the newbies reading)

edit: I have amended my code so it does what I think it should:

function saveState()
local save = fs.open("status","w")
  save.writeLine(username)
  save.writeLine(adminname)
  save.writeLine(userpass)
  save.writeLine(adminpass)
  save.writeLine(reactor)
  save.writeLine(coolant)
  save.writeLine(macerator)
  save.writeLine(furnace)
  save.writeLine(compressor)
  save.writeLine(extractor)
  save.writeLine(energystorage)
  save.writeLine(lights)
  save.close()
end
function loadState()
local load = fs.open("status","r")
  username = load.readLine()
  adminname = load.readLine()
  userpass = load.readLine()
  adminpass = load.readLine()
  reactor = load.readLine()
  coolant = load.readLine()
  macerator = load.readLine()
  furnace = load.readLine()
  compressor = load.readLine()
  extractor = load.readLine()
  energystorage = load.readLine()
  lights = load.readLine()
  load.close()
end
I think this is what I need it to do, but let me know. Hopefully this writes the state of each color, and then loads the state of each line written.
MysticT #6
Posted 07 August 2012 - 08:03 PM
Just remember that everything you read/write from/to files must be strings (unless you open it in binary mode).
Cranium #7
Posted 07 August 2012 - 08:24 PM
a boolean counts as a string, right?
cant_delete_account #8
Posted 07 August 2012 - 08:27 PM
a boolean counts as a string, right?
I'm not sure, but you should use tostring(boolean) when you write it. But when you read it from the file you will have to convert it from a string back to a boolean.
MysticT #9
Posted 07 August 2012 - 08:35 PM
a boolean counts as a string, right?
No, a boolean is a boolean, a string is a string. You can (like thesbros said) convert a boolean to string with tostring, and then do something like:

local s = file.readLine()
local b
if s == "true" then
  b = true
elseif s == "false" then
  b = false
end
when reading from the file.
Cranium #10
Posted 07 August 2012 - 08:59 PM
Ok… so I have a menu system that accepts user input to determine each of those variables previously stated. Many of those will be listed as true/false. If I have this right, when I have them initially declared by the input, I need to use this for example:

-- as I am declaring variables
username = tostring(yN())
adminname = tostring(yN())
--etc down the line...
function yN() --function that returns the true/false that the user must input
local n=1
while true do
local x, y=term.getCursorPos()
term.clearLine()
if n==1 then write(">YES<   NO") else write (" YES   >NO<") end
term.setCursorPos(x, y)
a, b=os.pullEvent()
while a~="key" do a, b=os.pullEvent() end
if b==203 and n==2 then n=1 end
if b==205 and n==1 then n=2 end
if b==28 then print("") break end
end
if n==1 then return true end
if n==2 then return false end
return false
end
I got the code from the menu tutorial, and I hope this will allow me to declare my variables as I go down asking them to be added by the user. When I load them, how would I convert them back, or do I just need to edit the rest of my code to accept strings instead of booleans?
Cranium #11
Posted 07 August 2012 - 09:57 PM
Still looking for an answer on the last question. Any thoughts?
Lyqyd #12
Posted 08 August 2012 - 01:14 AM
Didn't you read MysticT's post just above? It answers the question you asked about loading them from the file.
Cranium #13
Posted 08 August 2012 - 01:29 AM
Didn't you read MysticT's post just above? It answers the question you asked about loading them from the file.
Sorry, just reread it, and realized what he meant… It has been a looong day at work. ;)/>/>
Ponder #14
Posted 08 August 2012 - 11:32 PM
Ok, so since I use that same function for other parts of the code, it would probably be easier to declare a new variable like this:

cool = colors.test(rs.getBundledOutput("back"), colors.blue)
rc = colors.test(rs.getBundledOutput("back"), colors.red)
Right? And then I can pretty much do the same for everything else?
I would just call back to that variable like this:

function saveState()
local save = fs.open("status","w")
  save.writeLine("..rc..")
  save.writeLine("..cool..")
  save.close()
end
If so, then the only thing I think I might have messed up on, is the concatenation. (the two periods(..), for the newbies reading)

Actually, I'd rather avoid that, since you already have a function to access that information, so it would be redundant to have the exact same code again. You should rather generalize your functions so that they just return the string and instead of simply calling them do this:

print (coolstat ())
This way you can use same function multiple times in your program and avoid writing the same code over and over. This is what function are about, encapsulate and generalize your code to increase its re-usability and save you time.

edit: I have amended my code so it does what I think it should:

function saveState()
local save = fs.open("status","w")
  save.writeLine(username)
  save.writeLine(adminname)
  save.writeLine(userpass)
  save.writeLine(adminpass)
  save.writeLine(reactor)
  save.writeLine(coolant)
  save.writeLine(macerator)
  save.writeLine(furnace)
  save.writeLine(compressor)
  save.writeLine(extractor)
  save.writeLine(energystorage)
  save.writeLine(lights)
  save.close()
end
function loadState()
local load = fs.open("status","r")
  username = load.readLine()
  adminname = load.readLine()
  userpass = load.readLine()
  adminpass = load.readLine()
  reactor = load.readLine()
  coolant = load.readLine()
  macerator = load.readLine()
  furnace = load.readLine()
  compressor = load.readLine()
  extractor = load.readLine()
  energystorage = load.readLine()
  lights = load.readLine()
  load.close()
end
I think this is what I need it to do, but let me know. Hopefully this writes the state of each color, and then loads the state of each line written.
Take a piece of chalk, go to the next chalkboard and write a couple of times: "Global variables are bad."
Especially in ComputerCraft, since all the code on a computer is executed by the same Lua interpreter. That means by declaring a global variable you create a variable that is accessible from any other program on that computer. You don't really want that and it creates a lot of problems with debugging, imagine that one program sets a variable and another program you run afterwards uses a variable of the same name. Suddenly, the second program runs just not as it should and it will take a lot to just come up with the idea, that there might be a different programs which disturbs yours. Same goes for globals in the same program, somewhere some function is just not doing what it should because some other function messed with a global in a way it shouldn't. It's just a pain in the ass, to debug that.
If you got a lot of variables to return, just stuff them in a table and return that table instead.
Cranium #15
Posted 08 August 2012 - 11:50 PM
Take a piece of chalk, go to the next chalkboard and write a couple of times: "Global variables are bad."
Especially in ComputerCraft, since all the code on a computer is executed by the same Lua interpreter. That means by declaring a global variable you create a variable that is accessible from any other program on that computer. You don't really want that and it creates a lot of problems with debugging, imagine that one program sets a variable and another program you run afterwards uses a variable of the same name. Suddenly, the second program runs just not as it should and it will take a lot to just come up with the idea, that there might be a different programs which disturbs yours. Same goes for globals in the same program, somewhere some function is just not doing what it should because some other function messed with a global in a way it shouldn't. It's just a pain in the ass, to debug that.
If you got a lot of variables to return, just stuff them in a table and return that table instead.
Lol. The fact that global variables can interfere with other programs actually helps me in this instance. I am saving these variables to be used with other programs. This is just a small part of my first_run program that I will be using for my Master Control Program. I do understand that global variables are something to avoid.
Lyqyd #16
Posted 09 August 2012 - 01:55 AM
Take a piece of chalk, go to the next chalkboard and write a couple of times: "Global variables are bad."
Especially in ComputerCraft, since all the code on a computer is executed by the same Lua interpreter. That means by declaring a global variable you create a variable that is accessible from any other program on that computer. You don't really want that and it creates a lot of problems with debugging, imagine that one program sets a variable and another program you run afterwards uses a variable of the same name. Suddenly, the second program runs just not as it should and it will take a lot to just come up with the idea, that there might be a different programs which disturbs yours. Same goes for globals in the same program, somewhere some function is just not doing what it should because some other function messed with a global in a way it shouldn't. It's just a pain in the ass, to debug that.
If you got a lot of variables to return, just stuff them in a table and return that table instead.
Lol. The fact that global variables can interfere with other programs actually helps me in this instance. I am saving these variables to be used with other programs. This is just a small part of my first_run program that I will be using for my Master Control Program. I do understand that global variables are something to avoid.

You'd be better off reading the values from a file in each program that needs them and writing them back to the file, keeping everything local.
Cranium #17
Posted 09 August 2012 - 02:09 AM
Take a piece of chalk, go to the next chalkboard and write a couple of times: "Global variables are bad."
Especially in ComputerCraft, since all the code on a computer is executed by the same Lua interpreter. That means by declaring a global variable you create a variable that is accessible from any other program on that computer. You don't really want that and it creates a lot of problems with debugging, imagine that one program sets a variable and another program you run afterwards uses a variable of the same name. Suddenly, the second program runs just not as it should and it will take a lot to just come up with the idea, that there might be a different programs which disturbs yours. Same goes for globals in the same program, somewhere some function is just not doing what it should because some other function messed with a global in a way it shouldn't. It's just a pain in the ass, to debug that.
If you got a lot of variables to return, just stuff them in a table and return that table instead.
Lol. The fact that global variables can interfere with other programs actually helps me in this instance. I am saving these variables to be used with other programs. This is just a small part of my first_run program that I will be using for my Master Control Program. I do understand that global variables are something to avoid.

You'd be better off reading the values from a file in each program that needs them and writing them back to the file, keeping everything local.
So put local in front of every variable??? They would only exist in that function though. The program was posted in the Programs section, labelled Master Control Program. Check it out, and see what I mean. I don't want to post my code twice if I don't have to…
Lyqyd #18
Posted 09 August 2012 - 02:27 AM
Get the values into a local table in the load function, return the table. Using global variables is just bad news. I also didn't see any other programs involved.
Cranium #19
Posted 09 August 2012 - 03:00 AM
I don't have any yet…. Working on them as we speak. So as I write them, going through the menus and then saving them, label them as local, then load them as global?
Lyqyd #20
Posted 09 August 2012 - 04:18 AM
There's no need to have any of it as globals. You pass the data around inside the program, write it to the file, read it in the next program, etc.
Ponder #21
Posted 09 August 2012 - 02:01 PM
Also if a function returns data you need in multiple programs, make an API out of it.


So put local in front of every variable???

Yeah, Lua is not really funny when it comes to this, guess why I cannot motivate myself to start a bigger project in CC.
Cranium #22
Posted 09 August 2012 - 02:24 PM
Well I tried listing them as local, and it didn't work. As I said before, they are not existing outside of that function UNLESS I declare them global. As much as I appreciate the tips, but I think that this would be the only way… And I don't know how to make an API, by the way. If that is better, then I need to find out how to create one.
Lyqyd #23
Posted 09 August 2012 - 03:06 PM
Well I tried listing them as local, and it didn't work. As I said before, they are not existing outside of that function UNLESS I declare them global. As much as I appreciate the tips, but I think that this would be the only way… And I don't know how to make an API, by the way. If that is better, then I need to find out how to create one.

It's not the only way; you've obviously skipped most of the suggestion. There were more steps than just "put 'local' in front of everything."
Cranium #24
Posted 09 August 2012 - 03:13 PM
Sorry, I'm just not getting it then… Tell you what: here is the code I have used, let me know where I'm supposed to declare them as local. I have no idea how to do it like you are saying.
Warning: it's over 300 lines.
Spoiler

--Made by Craniumkid22
--This code is free to use, under a few conditions:
--1. DO NOT claim this as your own work!
--2. If you change this code, feel free to contact me on the CC forums, user-Craniumkid22.
--3. if you have questions about any of this code, feel free to contact me as well.

--screen functions
function title()
term.clear()
term.setCursorPos(1,1)
print("	 Welcome to Master Control initialization!")
print("	   Please read each selection carefully.")
print("		  If you mess up, press CTRL + T")
print("			 And run the wizard again.")
term.setCursorPos(1,9)
end
--end screen functions
function yN() --this code used with permission from the tutorials section of the CC forums.
local n=1
while true do
local x, y=term.getCursorPos()
term.clearLine()
if n==1 then write(">YES<   NO") else write (" YES   >NO<") end
term.setCursorPos(x, y)
a, b=os.pullEvent()
while a~="key" do a, b=os.pullEvent() end
if b==203 and n==2 then n=1 end
if b==205 and n==1 then n=2 end
if b==28 then print("") break end
end
if n==1 then return true end
if n==2 then return false end
return false
end
function opt(m) --this code used with permission from the tutorials section of the CC forums.
n=1
l=#m
while true do
term.clear()
term.setCursorPos(1,2)
for i=1, l, 1 do
if i==n then print(i, " ["..m[i].."]") else print(i, " ", m[i]) end
end
a, b= os.pullEventRaw()
if a == "key" then
if b==200 and n>1 then n=n-1 end
if b==208 and n<=l then n=n+1 end
if b==28 then break end
end
end
term.clear() term.setCursorPos(1,1)
return n
end
function saveState()
local save = fs.open("status","w")
  save.writeLine(frun)
  save.writeLine(username)
  save.writeLine(userpass)
  save.writeLine(adminname)
  save.writeLine(adminpass)
  save.writeLine(reactor)
  save.writeLine(coolant)
  save.writeLine(macerator)
  save.writeLine(furnace)
  save.writeLine(compressor)
  save.writeLine(extractor)
  save.writeLine(powertype)
  save.writeLine(energystorage)
  save.writeLine(lights)
  save.writeLine(lcolor)
  save.writeLine(rcolor)
  save.writeLine(ccolor)
  save.writeLine(mcolor)
  save.writeLine(fcolor)
  save.writeLine(cxcolor)
  save.writeLine(xcolor)
  save.writeLine(pcolor)
  save.writeLine(Cstat)
  save.writeLine(RCstat)
  save.writeLine(Mstat)
  save.writeLine(Fstat)
  save.writeLine(CXstat)
  save.writeLine(Xstat)
  save.close()
end
function loadState()
local load = fs.open("status","r")
  local frun = load.readLine()
  username = load.readLine()
  userpass = load.readLine()
  adminname = load.readLine()
  adminpass = load.readLine()
  reactor = load.readLine()
  coolant = load.readLine()
  macerator = load.readLine()
  furnace = load.readLine()
  compressor = load.readLine()
  extractor = load.readLine()
  powertype = load.readLine()
  energystorage = load.readLine()
  lights = load.readLine()
  lcolor = load.readLine()
  rcolor = load.readLine()
  ccolor = load.readLine()
  mcolor = load.readLine()
  fcolor = load.readLine()
  cxcolor = load.readLine()
  xcolor = load.readLine()
  pcolor = load.readLine()
  Cstat = load.readLine()
  RCstat = load.readLine()
  Mstat = load.readLine()
  Fstat = load.readLine()
  CXstat = load.readLine()
  Xstat = load.readLine()
  load.close()
end
-- variables
colorOpt={
"Redstone/Red alloy wire",
"White",
"Orange",
"Magenta",
"Light Blue",
"Yellow",
"Lime",
"Pink",
"Gray",
"Light Gray",
"Cyan",
"Purple",
"Blue",
"Brown",
"Green",
"Red",
"Black"
}
eType={
"BatBox",
"MFE",
"MFSU"
}
pType={
"Generator",
"Geothermal Generator",
"Water Mill",
"Wind Mill",
"Solar Panel",
"Nuclear Reactor",
"Redstone Engine",
"Steam Engine",
"Combustion Engine"
}
--end variables
while true do
title()
  while true do
    print("Please enter Administrator name:")
    adminname = read()
    if adminname == "" then
	  print("Admin name cannot be blank")
   sleep(1)
   title()
    else
	  break
    end
  end
title()
  while true do
    while true do
	  print("Please enter Administrator password:")
	  tempadmin = read("*")
   if tempadmin == "" then
	 print("Password cannot be blank")
	 sleep(1)
	 title()
   else
	 break
   end
  end
title()
  while true do
    print("Please re-enter password:")
    tempadmin2 = read("*")
if tempadmin2 == "" then
   print("Password cannot be blank")
   sleep(1)
   title()
else
   break
end
  end
title()
	  if tempadmin ~= tempadmin2 then
	    print("Passwords do not match. Please try again.")
  sleep(1)
	 title()
	  elseif tempadmin == tempadmin2 then
	    adminpass = tempadmin
	    break
	  end
  end
  title()
  print("Thank you. Admin profile created.")
  sleep(1)
  title()
  while true do
  print("Please enter User name:")
  tempusername = read()
    if tempusername == adminname then
   print("Cannot have User name the same as Administrator name.")
   sleep(1)
	  title()
    elseif tempusername == "" then
	  print("User name cannot be blank.")
	  sleep(1)
	  title()
    else
	  username = tempusername
   break
    end
title()
  end
  title()
  while true do
    while true do
	  print("Please enter User password:")
	  tempuser = read("*")
	  if tempuser == "" then
	    print("Password cannot be blank.")
	    sleep(1)
	    title()
	  else
	    break
	  end
	  title()
    end
    while true do
   title()
	  print("Pleas re-enter password:")
	  tempuser2 = read("*")
	  if tempuser2 == "" then
	    print("Password cannot be blank.")
	    sleep(1)
	    title()
	  else
	    break
	  end
    end
	  title()
	    if tempuser ~= tempuser2 then
		  print("Passwords do not match. Please try again.")
    sleep(1)
    title()
	    elseif tempuser == tempuser2 then
		  userpass = tempuser
		  break
	    end
    end
  title()
  print("Thank you. User profile created.")
  sleep(1)
  title()
  while true do
  print("Do you have lighting that you want to control?")
    lights = yN()
if lights == true then
	  term.clear()
   term.setCursorPos(1,9)
   print("		   What color are you using?")
   sleep(1.5)
   lcolor = tostring(opt(colorOpt))
   break
else
lights = false
   break
end
  end
  while true do
    title()
  print("What type of power are you using?")
    sleep(2)
    powertype = tostring(opt(pType))
	 while powertype == "6" do
		  title()
		  print("Do you want this computer to control your reactor?")
		   reactor = yN()
	   if reactor == true then
		 term.clear()
		 term.setCursorPos(1,9)
		 print("		   What color are you using?")
		 sleep(1.5)
		 rcolor = tostring(opt(colorOpt))
   pcolor = false
	   else
	  reactor = false
    end
  break
	 end
	  while reactor == true do
	    title()
	    print("Do you have an independant coolant system?")
		  coolant = yN()
	 if coolant == true then
	   term.clear()
	   term.setCursorPos(1,9)
	   print("		   What color are you using?")
	   sleep(1.5)
	   ccolor = tostring(opt(colorOpt))
	 else
    coolant = false
	 end
   break
   end
if powertype ~= "6" then
	  term.clear()
	  term.setCursorPos(1,9)
	  print("		   What color are you using?")
	  sleep(1.5)
	  pcolor = tostring(opt(colorOpt))
end
break
    end
  while true do
    title()
  print("What type of energy storage are you using?")
    sleep(2)
    energystorage = tostring(opt(eType))
break
  end
  while true do
    title()
  print("Would you like to control an IC2 Macerator?")
    macerator = yN()
if macerator == true then
   term.clear()
   term.setCursorPos(1,9)
   print("		   What color are you using?")
   sleep(1.5)
   mcolor = tostring(opt(colorOpt))
   break
else
   macerator = false
   break
end
  end
  while true do
    title()
  print("Would you like to control an IC2 Furnace?")
    furnace = yN()
if furnace == true then
   term.clear()
   term.setCursorPos(1,9)
   print("		   What color are you using?")
   sleep(1.5)
   fcolor = tostring(opt(colorOpt))
   break
else
   macerator = false
   break
end
  end
  while true do
    title()
  print("Would you like to control an IC2 Compressor?")
    compressor = yN()
if compressor == true then
   term.clear()
   term.setCursorPos(1,9)
   print("		   What color are you using?")
   sleep(1.5)
   cxcolor = tostring(opt(colorOpt))
   break
else
   compressor = false
   break
end
  end
  while true do
    title()
  print("Would you like to control an IC2 Extractor?")
    extractor = yN()
if extractor == true then
   term.clear()
   term.setCursorPos(1,9)
   print("		   What color are you using?")
   sleep(1.5)
   xcolor = tostring(opt(colorOpt))
   break
else
   compressor = false
   break
end
  end
local frun = true
saveState()
break
end
Lyqyd #25
Posted 09 August 2012 - 03:46 PM
Okay. Once I get home this afternoon, I'll show you what I'm talking about.
Cranium #26
Posted 09 August 2012 - 03:52 PM
That would be helpful. I understand that global variables are bad, I just don't know any way around that in this program.
Lyqyd #27
Posted 10 August 2012 - 02:28 AM
What's with all the unnecessary 'while true do' loops in the setup portion? You break no matter which selection they choose, so why bother using the loop at all?

Also, you use probably the most atrocious indentation scheme I think I've ever seen. None of it makes any sense.

Okay, so this uses a slightly different file format than the one you had, but it significantly reduces the amount of space the loading and saving functions take up. Each line is 'type,color,status'. It's probably best to continue to not actually use any data from the file in the wizard and just overwrite everything. I made a few other changes and ended up dropping about eighty lines. Let me know if you have any questions or if it fails to run.


--Made by Craniumkid22
--This code is free to use, under a few conditions:
--1. DO NOT claim this as your own work!
--2. If you change this code, feel free to contact me on the CC forums, user-Craniumkid22.
--3. if you have questions about any of this code, feel free to contact me as well.

--screen functions
local function title()
    term.clear()
    term.setCursorPos(1,1)
    print("  Welcome to Master Control initialization!")
    print("    Please read each selection carefully.")
    print("		   If you mess up, press CTRL + T")
    print("				  And run the wizard again.")
    term.setCursorPos(1,9)
end

--end screen functions
local function yN() --this code used with permission from the tutorials section of the CC forums.
    local n=1
    while true do
        local x, y=term.getCursorPos()
        term.clearLine()
        if n==1 then write(">YES<   NO") else write (" YES   >NO<") end
        term.setCursorPos(x, y)
        a, b=os.pullEvent()
        while a~="key" do
            a, b=os.pullEvent()
        end
        if b==203 and n==2 then n=1 end
        if b==205 and n==1 then n=2 end
        if b==28 then print("") break end
    end
    if n==1 then return true end
    if n==2 then return false end
    return false
end

local function opt(m) --this code used with permission from the tutorials section of the CC forums.
    n=1
    l=#m
    while true do
        term.clear()
        term.setCursorPos(1,2)
        for i=1, l, 1 do
            if i==n then print(i, " ["..m[i].."]") else print(i, " ", m[i]) end
        end
        a, b= os.pullEventRaw()
        if a == "key" then
            if b==200 and n>1 then n=n-1 end
            if b==208 and n<=l then n=n+1 end
            if b==28 then break end
        end
    end
    term.clear() term.setCursorPos(1,1)
    return n
end

local function saveState(saveTable)
    local file = io.open("status", "w")
    if file then
        for eNum, eInfo in ipairs(saveTable) do
            file:write(eInfo.type..","..eInfo.color..","..eInfo.status)
        end
        file:close()
    end
end

local function loadState()
    local loadTable = {}
    local file = io.open("status", "r")
    if file then
        readLine = file:read("*l")
        while readLine do
            local lineTable = {}
            lineTable.type, lineTable.color, lineTable.status = string.match(readLine, "(%a+),(%a+),(%a+)")
            if lineTable.type then
                table.insert(loadTable, lineTable)
            end
            readLine = file:read("*l")
        end
        file:close()
    end
    return loadTable
end

-- variables
local colorOpt={
    "Redstone/Red alloy wire",
    "White",
    "Orange",
    "Magenta",
    "Light Blue",
    "Yellow",
    "Lime",
    "Pink",
    "Gray",
    "Light Gray",
    "Cyan",
    "Purple",
    "Blue",
    "Brown",
    "Green",
    "Red",
    "Black"
}

local eType={
    "BatBox",
    "MFE",
    "MFSU"
}

local pType={
    "Generator",
    "Geothermal Generator",
    "Water Mill",
    "Wind Mill",
    "Solar Panel",
    "Nuclear Reactor",
    "Redstone Engine",
    "Steam Engine",
    "Combustion Engine"
}

local controlTable = {}

--end variables
while true do
    local adminTable = {type = "admin"}
    local tempadmin, tempadmin2, tempusername, tempuser, tempuser2
    local userTable = {type = "user"}
    title()
    while true do
        print("Please enter Administrator name:")
        adminTable.color = read()
        if adminTable.color == "" then
            print("Admin name cannot be blank")
            sleep(1)
            title()
        else
            break
        end
    end
    title()
    while true do
        while true do
            print("Please enter Administrator password:")
            tempadmin = read("*")
            if tempadmin == "" then
                print("Password cannot be blank")
                sleep(1)
                title()
            else
                break
            end
        end
        title()
        while true do
            print("Please re-enter password:")
            tempadmin2 = read("*")
            if tempadmin2 == "" then
                print("Password cannot be blank")
                sleep(1)
                title()
            else
                break
            end
        end
        title()
        if tempadmin ~= tempadmin2 then
            print("Passwords do not match. Please try again.")
            sleep(1)
            title()
        elseif tempadmin == tempadmin2 then
            adminTable.status = tempadmin
            break
        end
    end
    title()
    print("Thank you. Admin profile created.")
    sleep(1)
    title()
    while true do
        print("Please enter User name:")
        tempusername = read()
        if tempusername == adminTable.color then
            print("Cannot have User name the same as Administrator name.")
            sleep(1)
            title()
        elseif tempusername == "" then
            print("User name cannot be blank.")
            sleep(1)
            title()
        else
            userTable.color = tempusername
            break
        end
        title()
    end
    title()
    while true do
        while true do
            print("Please enter User password:")
            tempuser = read("*")
        if tempuser == "" then
            print("Password cannot be blank.")
            sleep(1)
            title()
        else
            break
        end
        title()
    end
    while true do
        title()
        print("Pleas re-enter password:")
        tempuser2 = read("*")
        if tempuser2 == "" then
            print("Password cannot be blank.")
            sleep(1)
            title()
        else
            break
        end
    end
    title()
    if tempuser ~= tempuser2 then
        print("Passwords do not match. Please try again.")
        sleep(1)
        title()
    elseif tempuser == tempuser2 then
        userTable.status = tempuser
        break
    end
    table.insert(controlTable, adminTable)
    table.insert(controlTable, userTable)
end
title()
print("Thank you. User profile created.")
sleep(1)
title()

while true do
    print("Do you have lighting that you want to control?")
    if yN() then
        local deviceTable = {type = "lights"}
        term.clear()
        term.setCursorPos(1,9)
        print("				 What color are you using?")
        sleep(1.5)
        deviceTable.color = tostring(opt(colorOpt))
        table.insert(controlTable, deviceTable)
    else
        break
    end
end

title()
print("What type of power are you using?")
sleep(2)
local powertype = tostring(opt(pType))
if powertype == "6" then
    title()
    print("Do you want this computer to control your reactor?")
    if yN() then
        local deviceTable = {type = "reactor"}
        term.clear()
        term.setCursorPos(1,9)
        print("				   What color are you using?")
        sleep(1.5)
        deviceTable.color = tostring(opt(colorOpt))
        table.insert(controlTable, deviceTable)
        print("Do you have an independant coolant system?")
        if yN() then
            local deviceTable = {type = "coolant"}
            term.clear()
            term.setCursorPos(1,9)
            print("				 What color are you using?")
            sleep(1.5)
            deviceTable.color = tostring(opt(colorOpt))
            table.insert(controlTable, deviceTable)
        end
    end
else
    local deviceTable = {type = tolower(string.match(pType[powertype], "^(%a+)"))}
    term.clear()
    term.setCursorPos(1,9)
    print("				  What color are you using?")
    sleep(1.5)
    deviceTable.color = tostring(opt(colorOpt))
    table.insert(controlTable, deviceTable)
end

title()
print("What type of energy storage are you using?")
sleep(2)
local deviceTable = {type = "energy", color = tolower(eType[opt(eType)])}
table.insert(controlTable, deviceTable)

while true do
    title()
    print("Would you like to control another device?")
    type = typeMenu() --create a type menu function to determine Macerator/Furnace/Compressor/Extractor/Cancel, returning nil on cancel.
    if type == nil then break end
    local deviceTable = {}
    deviceTable.type = type
    term.clear()
    term.setCursorPos(1,9)
    print("				 What color are you using?")
    sleep(1.5)
    deviceTable.color = tostring(opt(colorOpt))
    table.insert(controlTable, deviceTable)
    end
end
 
local frun = true
saveState(controlTable)
end
Cranium #28
Posted 10 August 2012 - 04:11 AM
Well, I tried running this, but It just keeps looping at the first selection for the lights. I did however change my code…again. ;)/>/>
I think it works better, but instead of running out this help topic, would you mind if I bounce my code with you through PM?
Lyqyd #29
Posted 10 August 2012 - 04:13 AM
Did you try choosing no at that point?

Yes, you can PM me. I do think that you should thoroughly check out the code that I posted, though. It's set up to allow for more than just one of things, which might be a nice feature.
Cranium #30
Posted 10 August 2012 - 10:20 PM
So now that I understand that global variables are bad, I think that I know to declare my variables by using a table. I just don't know how. When declaring them, How would I have them getting sent to a table? I know to do something like local var = menuOpt() and then saying like table[1] = var. Problem is, how would I have that come from the table to my save command?

Current save command:

function saveState()
local save = fs.open("status","w")
save.writeLine(frun)
save.writeLine(adminname)
save.writeLine(adminpass)
save.writeLine(username)
save.writeLine(userpass)
save.writeLine(lights)
save.writeLine(lcolor)
save.writeLine(Lstat)
save.writeLine(powertype)
save.writeLine(pcolor)
save.writeLine(reactor)
save.writeLine(rcolor)
save.writeLine(RCstat)
save.writeLine(coolant)
save.writeLine(ccolor)
save.writeLine(Cstat)
save.writeLine(energystorage)
save.writeLine(macerator)
save.writeLine(Mstat)
save.writeLine(mcolor)
save.writeLine(furnace)
save.writeLine(fcolor)
save.writeLine(Fstat)
save.writeLine(compressor)
save.writeLine(cxcolor)
save.writeLine(CXstat)
save.writeLine(extractor)
save.writeLine(xcolor)
save.writeLine(Xstat)
save.close()
end
And how would I have it come back from the file in table format? My current load code is this:

function loadState()
local load = fs.open("status","r")
frun = load.readLine()
adminname = load.readLine()
adminpass = load.readLine()
username = load.readLine()
userpass = load.readLine()
lights = load.readLine()
lcolor = load.readLine()
powertype = load.readLine()
pcolor = load.readLine()
reactor = load.readLine()
rcolor = load.readLine()
RCstat = load.readLine()
coolant = load.readLine()
ccolor = load.readLine()
Cstat = load.readLine()
energystorage = load.readLine()
macerator = load.readLine()
mcolor = load.readLine()
Mstat = load.readLine()
furnace = load.readLine()
fcolor = load.readLine()
Fstat = load.readLine()
compressor = load.readLine()
cxcolor = load.readLine()
CXstat = load.readLine()
extractor = load.readLine()
xcolor = load.readLine()
Xstat = load.readLine()
load.close()
end
Lyqyd #31
Posted 11 August 2012 - 01:00 AM
Like this, as posted above:


local function saveState(saveTable)
    local file = io.open("status", "w")
    if file then
        for eNum, eInfo in ipairs(saveTable) do
            file:write(eInfo.type..","..eInfo.color..","..eInfo.status)
        end
        file:close()
    end
end

local function loadState()
    local loadTable = {}
    local file = io.open("status", "r")
    if file then
        readLine = file:read("*l")
        while readLine do
            local lineTable = {}
            lineTable.type, lineTable.color, lineTable.status = string.match(readLine, "(%a+),(%a+),(%a+)")
            if lineTable.type then
                table.insert(loadTable, lineTable)
            end
            readLine = file:read("*l")
        end
        file:close()
    end
    return loadTable
end

Cranium #32
Posted 11 August 2012 - 02:21 AM
So how do I have it save a variable? Just put the variable in the () when calling to the saveState() function?
For that matter, how would I have the table called upon in another program?
Lyqyd #33
Posted 11 August 2012 - 02:44 AM
No, basically, you load the table in a program, use or modify the variables inside of it, then save it. Another program then loads it, etc. The loaded table is a table of tables, each of which has three entries (type, color, and status). So, you could access it:

controlTable = loadState()

controlTable[3].type would be the third entry's type field. You can loop through the tables to check for things you're interested in, etc.

Then just saveState(controlTable) when you're done.
Cranium #34
Posted 11 August 2012 - 03:41 AM
I'm sorry, either I'm slow today, or this is way confusing… When I say, "do you want to control lights?" and it returns either true false, and then asks what color I'm using which will give me a number from 1-17, how would I save that state using the method you described?
Lyqyd #35
Posted 11 August 2012 - 03:58 AM

--elsewhere above:
local controlTable = {}

local function colorConvert(color)
if color > 1 then
  return 2^(color - 2)
else
  return 0
end
end

--new table instance to add to the controlTable.
local deviceTable = {type="lights"}
print("Gimme the color!")
--runs the option function, passes the chosen option to the color conversion function, then stores the value in our new table instance.
deviceTable.color = colorConvert(opt(colorOpt))
--we do not have a status set yet (though it may be a good idea to set a default status for the purposes of the write to the file).
deviceTable.status = "off"
--then add our new table instance to our table of controls.
table.insert(controlTable, deviceTable)
--and save our controlTable to the file
saveState(controlTable)
Cranium #36
Posted 11 August 2012 - 04:38 AM
So where I see color and status after deviceTable, that's where I put my variable? For lights, it would be for example:

local controlTable = {}

local function colorConvert(color)
if color > 1 then
return 2^(color - 2)
else
return 0
[color="#000000"]end[/color]
[color=#000000]end[/color]

[color=#000000]--before asking my question for the lights[/color]
local deviceTable = {type="lights"}
--as I am declaring the status of true/false
deviceTable.status = yN() --which will return either true/false
--as I am declaring the color
devicetable.color =colorConvert(opt(colorOpt))
--now adding what we just declared into the table
table.insert(controlTable, deviceTable)
--and now saving the table to the file
saveState(controlTable)
I think I got it, PLEASE correct me if I'm wrong. I'm just someone who learns by doing, not reading. So bear with me. ;)/>/>
Lyqyd #37
Posted 11 August 2012 - 04:42 AM
Looks about right, but I don't know what the FS write call will do when you tell it to write a boolean to the file. May want to pass the status part through tostring in the save function and add a little code to interpret the string back to a boolean in the loading function.
Cranium #38
Posted 11 August 2012 - 04:45 AM
Way ahead on that one. In my true/false menu, I changed it so it will return a string. O can change it to anything really…so I guess maybe I should start early and do string without boolean.