This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Loop through variables
#1
Hi

Is it possible to loop through a set of variables, or maybe determine variable name depending on other values?

I have a project where I need to count the presence for each ventilation system for each floor to be able to calculate the percentage of offices that are in use. For this I need two variables for each system for each floor; one for the number of occupied offices and one for the total number of offices.

In the name and address of the objects I can find both the floor and the ventilation system, so what I want to do is to scan through all the occupied-addresses and add values to the different variables depending on the value of the addresses.

I more or less has it working, but there is a lot of if/elseif and so on to be able to check it all. So I was thinking there must be a more elegant way to do it.

The code is not done yet, I still need to transfer values to group addresses, but this is what I have so far:

 
Code:
obj = db:getall('SELECT name FROM objects WHERE name LIKE "%STATUS_OCCUPIED%"')

calcWeight = false --Bestemmer om vekt skal medregnes i totalt antall OCCUPIED-adresser. Med false vil hver adresse kun telle som 1.

local p1_03_04count = 0
local p1_03_04occ = 0
local p2_03_04count = 0
local p2_03_04occ = 0
local p3_03_04count = 0
local p3_03_04occ = 0
local p4_03_04count = 0
local p4_03_04occ = 0
local p5_03_04count = 0
local p5_03_04occ = 0

local p1_05count = 0
local p1_05occ = 0
local p2_05count = 0
local p2_05occ = 0
local p3_05count = 0
local p3_05occ = 0
local p4_05count = 0
local p4_05occ = 0
local p5_05count = 0
local p5_05occ = 0

local p1_02count = 0
local p1_02occ = 0
local p2_02count = 0
local p2_02occ = 0
local p3_02count = 0
local p3_02occ = 0
local p4_02count = 0
local p4_02occ = 0






for _, name in ipairs(obj) do
  adr = grp.find(name.name)
  gaWeight = string.gsub(name.name, 'STATUS', 'WEIGHT')
  weight = grp.getvalue(gaWeight)
  value = toboolean(grp.getvalue(name.name))
  if value then value = 1 else value = 0 end
  etasje = string.split(adr.address, '/')[2]
  agg = string.split(string.split(adr.name, '360.')[2], ' ')[1]
 
  --Oppretter adresse for vekting dersom den ikke finnes og setter vekttallet til 1.
  if grp.find(gaWeight) == nil then
    address = grp.create({
        datatype = dt.uint16,
        virtual = true,
        name = gaWeight,
        comment = '',
      })
    grp.write(gaWeight, 1)
  end
  --log(value, etasje, agg, weight)
 
  if etasje == '1' then
    if agg == '02' then
      log(name.name, value, etasje, agg, weight)
      p1_02count = p1_02count + 1
      p1_02occ = p1_02occ + (value * weight)
    elseif agg == '03_04' then
      p1_03_04count = p1_03_04count + 1
      p1_03_04occ = p1_03_04occ + (value * weight)
    elseif agg == '05' then
      p1_05count = p1_05count + 1
      p1_05occ = p1_05occ + (value * weight)
    end
  elseif etasje == '2' then
    if agg == '02' then
      --log(name.name, value, etasje, agg, weight)
      p2_02count = p2_02count + 1
      p2_02occ = p2_02occ + (value * weight)
    elseif agg == '03_04' then
      p2_03_04count = p2_03_04count + 1
      p2_03_04occ = p2_03_04occ + (value * weight)
    elseif agg == '05' then
      p2_05count = p2_05count + 1
      p2_05occ = p2_05occ + (value * weight)
    end
  elseif etasje == '3' then
    if agg == '02' then
      --log(name.name, value, etasje, agg, weight)
      p3_02count = p3_02count + 1
      p3_02occ = p3_02occ + (value * weight)
    elseif agg == '03_04' then
      p3_03_04count = p3_03_04count + 1
      p3_03_04occ = p3_03_04occ + (value * weight)
    elseif agg == '05' then
      p3_05count = p3_05count + 1
      p3_05occ = p3_05occ + (value * weight)
    end
  elseif etasje == '4' then
    if agg == '02' then
      --log(name.name, value, etasje, agg, weight)
      p4_02count = p4_02count + 1
      p4_02occ = p4_02occ + (value * weight)
    elseif agg == '03_04' then
      p4_03_04count = p4_03_04count + 1
      p4_03_04occ = p4_03_04occ + (value * weight)
    elseif agg == '05' then
      p4_05count = p4_05count + 1
      p4_05occ = p4_05occ + (value * weight)
    end
  elseif etasje == '5' then
    if agg == '02' then
      --log(name.name, value, etasje, agg, weight)
      p5_02count = p5_02count + 1
      p5_02occ = p5_02occ + (value * weight)
    elseif agg == '03_04' then
      p5_03_04count = p5_03_04count + 1
      p5_03_04occ = p5_03_04occ + (value * weight)
    elseif agg == '05' then
      p5_05count = p5_05count + 1
      p5_05occ = p5_05occ + (value * weight)
    end
  end
 
   
 
 
  --log(adr.name, etasje, agg)
end

log(p1_02count, p1_02occ)
There are 10 kinds of people in the world; those who can read binary and those who don't  Cool
Reply
#2
Use arrays/tables to store data like this. Untested modified version of you code:
Code:
obj = db:getall('SELECT name FROM objects WHERE name LIKE "%STATUS_OCCUPIED%"')

data = {}
keys = { '02', '03_04', '05' }
for fid = 1, 5 do
  floor = {}
  for _, key in ipairs(keys) do
    floor[key] = {
      count = 0,
      occ = 0,
    }
  end
  data[fid] = floor
end

for _, name in ipairs(obj) do
  adr = grp.find(name.name)
  gaWeight = string.gsub(name.name, 'STATUS', 'WEIGHT')
  weight = grp.getvalue(gaWeight)
  value = toboolean(grp.getvalue(name.name))
  floor = tonumber(string.split(adr.address, '/')[2])
  agg = string.split(string.split(adr.name, '360.')[2], ' ')[1]
  
  --Oppretter adresse for vekting dersom den ikke finnes og setter vekttallet til 1.
  if grp.find(gaWeight) == nil then
    address = grp.create({
        datatype = dt.uint16,
        virtual = true,
        name = gaWeight,
        comment = '',
      })
    grp.write(gaWeight, 1)
    weight = 1
  end

  if data[floor] and data[floor][agg] then
    data[floor][agg].count = data[floor][agg].count + 1
    if value then
      data[floor][agg].occ = data[floor][agg].occ + weight
    end
  end
end

log(data)
Reply
#3
(11.02.2021, 14:28)admin Wrote: Use arrays/tables to store data like this. Untested modified version of you code:
Code:
obj = db:getall('SELECT name FROM objects WHERE name LIKE "%STATUS_OCCUPIED%"')

data = {}
keys = { '02', '03_04', '05' }
for fid = 1, 5 do
  floor = {}
  for _, key in ipairs(keys) do
    floor[key] = {
      count = 0,
      occ = 0,
    }
  end
  data[fid] = floor
end

for _, name in ipairs(obj) do
  adr = grp.find(name.name)
  gaWeight = string.gsub(name.name, 'STATUS', 'WEIGHT')
  weight = grp.getvalue(gaWeight)
  value = toboolean(grp.getvalue(name.name))
  floor = tonumber(string.split(adr.address, '/')[2])
  agg = string.split(string.split(adr.name, '360.')[2], ' ')[1]
 
  --Oppretter adresse for vekting dersom den ikke finnes og setter vekttallet til 1.
  if grp.find(gaWeight) == nil then
    address = grp.create({
        datatype = dt.uint16,
        virtual = true,
        name = gaWeight,
        comment = '',
      })
    grp.write(gaWeight, 1)
    weight = 1
  end

  if data[floor] and data[floor][agg] then
    data[floor][agg].count = data[floor][agg].count + 1
    if value then
      data[floor][agg].occ = data[floor][agg].occ + weight
    end
  end
end

log(data)

Great! 

I will test this out. It looks a lot more elegant than my solution. I believe I will be needing things like this in many other applications as well.
There are 10 kinds of people in the world; those who can read binary and those who don't  Cool
Reply
#4
OK, so I got this finnished and tested. It works very well. I added some extra info to the table to get more data available, other than that I kept most of the code from Admin.

Thanks for the great help in learing to code in this forum! It is always productive and on-the-spot help here!

I wont bother to post the final code as it is very project spesific, and probably not of interest to anyone else.
There are 10 kinds of people in the world; those who can read binary and those who don't  Cool
Reply


Forum Jump: