LogicMachine Forum
Loop through variables - Printable Version

+- LogicMachine 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.