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

Tweaking a simple program I made?

Started by PhatClowns, 11 July 2014 - 03:50 PM
PhatClowns #1
Posted 11 July 2014 - 05:50 PM
Okay, I made this little program for the Tekkit server I'm currently running. It's a program that runs on loop, displaying on a screen the amount of energy stored in one of the 24 Resonant Energy Cells in our facility. Here's the code:


local cells = {
  { p=peripheral.wrap("back"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_0"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_1"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_2"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_3"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_4"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_5"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_6"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_7"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_8"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_9"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_10"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_11"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_12"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_13"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_14"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_15"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_16"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_17"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_18"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_19"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_20"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_21"), n=0, max=0 },
  { p=peripheral.wrap("cofh_thermalexpansion_energycell_22"), n=0, max=0 }
}

function getLoss()
--This function is used to calculate the net flow of energy into the
--energy cells. It does so by measuring the cell energy, sleeping for
--1 tick, and then measuring it again.

local before = 0
local after = 0
for i=1,#cells do
  readCell(i)
  before = before + cells[i].n
  sleep(.05)
  readCell(i)
  after = after + cells[i].n
end

local net = after - before
x,y = m.getCursorPos()
m.setCursorPos(3,y+4)
if net < 0 then
  m.write("ENERGY USAGE: "..net)
  m.write(" RF/t")
elseif net > 0 then
  m.write("ENERGY GAIN: +"..net)
  m.write(" RF/t")
else
  m.write("NO NET CHANGE (0 RF/t)")
end

end

function readCell(cell)
--This reads the amount of energy in the given cell and sets it as
--the variable "n", as well as setting the maximum energy storage as the
--variable "max" in the table.

local p = cells[cell].p
cells[cell].n = p.getEnergyStored("unknown")
cells[cell].max = p.getMaxEnergyStored("unknown")

end


function display()
--This prints a list of all 24 cells, separates them into 3 columns, and
--lists the amount of energy stored in each.

for i=1,#cells do
  if i <= 10 then
				m.setCursorPos(3,1+i)
				m.write("CELL #"..i)
				m.write(": "..cells[i].n)
				m.write(" RF")
  elseif i <= 20 and i > 10 then
	m.setCursorPos(27,1+i-10)
				m.write("CELL #"..i)
				m.write(": "..cells[i].n)
				m.write(" RF")
  elseif i <= 30 and i > 20 then
	m.setCursorPos(51,1+i-20)
				m.write("CELL #"..i)
				m.write(": "..cells[i].n)
				m.write(" RF")
  end
end

end

function totalPrint()
--Prints the total storage capacity of all the cells, how much energy is
--stored, and the percentage of potential energy.

local total = 0
local totalMax = 0
for i=1,#cells do
  total = total + cells[i].n
  totalMax = totalMax + cells[i].max
end
local totalPC = ( ( total / totalMax ) * 100 )
local x,y = m.getCursorPos()
m.setCursorPos(3,y+10)
m.write("TOTAL: "..total)
m.write(" RF")
m.setCursorPos(3,y+11)
m.write("MAX: "..totalMax)
m.write(" RF")
m.setCursorPos(3,y+13)
m.write("STORED: "..totalPC)
m.write("%")

end

--Main Command Line
function main()
--Runs all the functions in order.

local isRunning = true
m = peripheral.wrap("monitor_0")
m.clear()
m.setTextScale(1.47)
while isRunning do
  for i=1,#cells do
	readCell(i)
  end
  m.clear()
  display()
  totalPrint()
  getLoss()
end

end

main()

It runs fine, no issues except the fact that it's a bit sluggish. It updates about every 2 seconds or so, and I fear that this may affect the accuracy of the displayed information.

So 2 questions:
1) Would the getLoss() function show inaccurate results? and
2) Is there any way I can clean up this code to make it run faster? It's about 139 lines of code.

From an aspiring programmer, thanks in advance! :D/>
flaghacker #2
Posted 11 July 2014 - 07:56 PM
1 )
If your tickrate isn't 20, it gives false results. If you have a lot of lag in your computercraft results, it can also be inaccurate.

2 )
a )
That first part (local cells = { }) can be cleaned up a lot. peripheral.getNames() returns a table containing a list of all attached peripherals, even trought a wired network. peripheral.call(<name>, <method>) can be used to call a method without wrapping the peripheral. I would suggest changing your hardcoded peripherals to something more like this:

local cells = {}
for _, name in pairs(peripheral.getNames()) do
  if peripheral.getType(name) == "cofh_thermalexpansion_energycell" then
	cells[#cells + 1] =
	  {
	  p = peripheral.wrap(name),
	  n = 0
	  max = 0
	  }
  end
end
It loops trought all peripherals, checks is they're an energy cell and then wraps them and initialized the "cells" table.

If you want to use peripheral.call(), then your starting loop should look like this:

local cells = {}
for _, name in pairs(peripheral.getNames()) do
  if peripheral.getType(name) == "cofh_thermalexpansion_energycell" then
	 cells[#cells + 1] = name
  end
end

--#and to use:
local energy = {}
local max = {}
for i, name in pairs(cells) do
  energy[i] = peripheral.call(name, "getEnergyStored", "unknown")
  max[i] = peripheral.call(name, "getMaxEnergyStored", "unknown")
end

--#if you want them in one table:
local info = {}
for i, name in pairs(cells) do
  info[i] =
	{
	name = name
	max = max[i]
	energy = energy[i]
	}
end
b )
It's a good idea to make all your variables local, so they don't clutter the global environment. See http://www.lua.org/pil/4.2.html for more info.

This is all untested code. It should work, but correct me if I made any mistakes.
Edited on 11 July 2014 - 06:31 PM
KingofGamesYami #3
Posted 11 July 2014 - 08:28 PM
When you compare name to "cofh_thermalexpansion_energycell", it will always be false. Try something like:

local compare = "cofh_thermalexpansion_energycell"
if name:sub( 1, #compare ) == compare then
flaghacker #4
Posted 11 July 2014 - 08:30 PM
When you compare name to "cofh_thermalexpansion_energycell", it will always be false. Try something like:

local compare = "cofh_thermalexpansion_energycell"
if name:sub( 1, #compare ) == compare then

Derp, fixed.
I use peripheral.getType(name).
PhatClowns #5
Posted 11 July 2014 - 09:10 PM
Okay, this might be a noob question… I've just never seen it before. But what exactly does using "in pairs()" do in a for loop? And also why is an "_" used as the start?
flaghacker #6
Posted 11 July 2014 - 09:24 PM
Read this to learn about the "in pairs": http://computercraft...ables_and_Loops

The "_" is a regular variable name. I need it there but I won't use it later in my script, so I call it "_". That's just a habit most people have. You'll understand why I need that variable thare once you read that link.

Sorry for this short post, I have to go right now!
Edited on 11 July 2014 - 07:25 PM