Logic Machine Forum
Loop through variables - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: Loop through variables (/showthread.php?tid=3163)



Loop through variables - Trond Hoyem - 11.02.2021

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)



RE: Loop through variables - admin - 11.02.2021

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)



RE: Loop through variables - Trond Hoyem - 11.02.2021

(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.


RE: Loop through variables - Trond Hoyem - 12.02.2021

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.