This made me remember a problem I had to workaround in the past, in the next alias:
; +++ CHANNELLIST / GET IRC STATS
; Input: $1 = network (optional)
; Output:
; $1 = total nets $2 = total chans $3 = total users
; $4 = amount Serve channels with USERDATA ON $5 = amount users on these channels
; $6 = amount of $4 with SCAN enabled $7 = amount users on these channels
; NOTE: do not put the level 3 loops on one line, it starts skipping last channel
alias SC_ChannelList_GetIRCStats {
SC_dl SC_ChannelList_GetIRCStats $1-
var %t = $SC_ts, %a = $asc(%t), %net = $1, %htotal = $SC_rh, %hud = $SC_rh, %hscan = $SC_rh, %4 = $chr(44)
var %total1 = $scon(0), %i1 = 1, %totalnet = 0, %totalchan = 0, %totalchanud = 0, %totalchanscan = 0
while (%i1 <= %total1) {
var %neti = $hget(SC_H,$+(Server,%4,$scon(%i1).cid)) | if (%neti == $null) { inc %i1 | continue }
if (%net != $null) && (%neti != %net) { inc %i1 | continue }
scid $scon(%i1).cid | if ($status != connected) { inc %i1 | continue }
inc %totalnet | var %total2 = $comchan($me,0), %i2 = 1
while (%i2 <= %total2) {
var %chan = $comchan($me,%i2) | tokenize %a $SC_ChannelList_Get(%neti,%chan,USERDATA,SCAN)
if ($1 == NOTFOUND) { inc %i2 | continue }
inc %totalchan | var %total3 = $nick(%chan,0), %i3 = 1
while (%i3 <= %total3) {
hadd %htotal $+(%neti,%t,$nick(%chan,%i3))
inc %i3
}
if ($1 != ON) { inc %i2 | continue }
inc %totalchanud | var %i3 = 1
while (%i3 <= %total3) {
hadd %hud $+(%neti,%t,$nick(%chan,%i3))
inc %i3
}
if ($2 != ON) { inc %i2 | continue }
inc %totalchanscan | var %i3 = 1
while (%i3 <= %total3) {
hadd %hscan $+(%neti,%t,$nick(%chan,%i3))
inc %i3
}
inc %i2
}
inc %i1
}
var %user = $hget(%htotal,0).item, %userud = $hget(%hud,0).item, %userscan = $hget(%hscan,0).item
hfree %htotal | hfree %hud | hfree %hscan | return %totalnet %totalchan %user %totalchanud %userud %totalchanscan %userscan
}
I have the habit of putting the code for a single loop on one line if its very short.
So initially those 3 level 3 loops looked like:
while (%i3 <= %total3) { hadd %htotal | $+(%neti,%t,$nick(%chan,%i3)) | inc %i3 }
But after some time I discovered the returned numbers were wrong.
It seemed to somehow skip the last iteration of the level 2 loop.
I discovered that, to make it correct, I had to spread the code out on more lines like this:
while (%i3 <= %total3) {
hadd %htotal $+(%neti,%t,$nick(%chan,%i3))
inc %i3
}
I just tried to write standalone reproduction code but my first attempts failed so I just made some test runs to be able to give some more info, by trying various combinations of single line level 3 loops:
This is the output when all level 3 loops have their code spreaded out on more lines:
Nets:3 Chans:19 Users:382 UDchans:3 UDusers:@124H124/127
These are the testruns, the amount Nets and Chans surely remained the same, it's possible User counts changed while testing because it was real sitation on IRC:
ScanChans:2 ScanUsers:117
i3 loop 1 on 1 line:
Nets:3 Chans:18 Users:345 UDchans:3 UDusers:@123H123/126 ScanChans:2 ScanUsers:116
i3 loop 2 on 1 line:
Nets:3 Chans:14 Users:222 UDchans:2 UDusers:@123H123/12 ScanChans:1 ScanUsers:2
i3 loop 3 on 1 line:
Nets:3 Chans:13 Users:220 UDchans:2 UDusers:@123H123/12 ScanChans:1 ScanUsers:2
i3 loops 1+2 on 1 line:
Nets:3 Chans:14 Users:165 UDchans:2 UDusers:@123H123/12 ScanChans:1 ScanUsers:2
i3 loops 2+3 on 1 line:
Nets:3 Chans:12 Users:166 UDchans:1 UDusers:@123H123/2 ScanChans:1 ScanUsers:2
i3 loops 1+2+3 on 1 line:
Nets:3 Chans:12 Users:190 UDchans:1 UDusers:@123H123/2 ScanChans:1 ScanUsers:2
I don't know if the problem here is the same one as from this topic (so also 'should be fixed for the next release').