System HandleGroups

quraji

zap
Reaction score
144
HandleGroup

What is it?
This is a library which contains a textmacro. This textmacro allows you to create a new 'group' with any handle you like. Units thought they were special because they were the only ones that got groups. No more! If you want a lightninggroup, so be it. Want a triggergroup? Be my guest.

How do I use it?
Run the text macro, and use the resulting struct type as if it were a new group type (with the supplied functions).

The Code:
JASS:
library HandleGroup
/* by quraji v1.03

    This library enables you to create your own group of any handle!
    The implemention is very simple. Just run the below textmacro where
    you want your new struct.
    Ex:
        //! runtextmacro CreateHandleGroup("lightning", "Lightning", "private", "8190")
        "lightning" is the handle type. This can be any handle type.
        "Lightning" is the desired name of that handle (for the methods/functions)
        "private" is the scope. This can be "private", "public" or "" for no scope
        "8190" is the number of possible struct instances (8190 is the default for vJass)
               -You can increase this to any number, at the cost of some performance.
    
    Method Definitions (x is the handle type, and X is the handle name):
    
        method forGroup takes code e returns nothing 
            This is the equivalent of the ForGroup for units. This uses a function interface instead of code. 
            e is the function to call for each handle in the group. Pass the name of any function that takes nothing and returns nothing
            You may use EnumHandleX or GetEnumHandleX() in e to refer to the enum handle
            Ex:
                call myhandlegroup.forGroup(myfunc)
        method clear takes nothing returns nothing
            This clears the handle group, but does not destroy it.
            
        method refresh takes nothing returns nothing
            Removes null handles from the group
            
        method getRandomX takes nothing returns x
            Returns a random handle from the group
            
        method firstOfGroup takes nothing returns x
            This returns the first handle of the group.
        
        method isXInGroup takes x h returns boolean
            Returns true if handle h is in the group, else false.
            
        method addX takes x h returns nothing
            Add a handle to the group.

        method removeX takes x h returns nothing
            Remove a handle from the group.
            
    There are also WC3 style function wrappers at the bottom, but I wont list them. (just look..this comment block is big enough already..)
    
*/
//! textmacro CreateHandleGroup takes handle, name, scope, size

globals
    $scope$ $handle$ EnumHandle$name$
endglobals

$scope$ struct $handle$group [$size$]
    
    private $handle$group last = 0
    private $handle$group prev = 0
    private $handle$group next = 0
    
    private $handle$ h
    private integer count = 0
    
    private method unlink takes nothing returns nothing
        set this.prev.next = this.next
        set this.next.prev = this.prev
        set this.last = this
        call this.destroy()
    endmethod
     
        /* for every handle in the group, call e
           use EnumHandleX or GetEnumHandleX to get the handle in the callback function, where X is the handle name
           Ex: set l = GetEnumHandleLightning()
               set l = EnumHandleLightning
          
           remember that function e must take nothing and return nothing
        */
    method forGroup takes enumfunc e returns nothing
        local $handle$group hg
        if (this.last!=this) then
            set hg = this.last
            loop
                exitwhen (hg==this)
                set EnumHandle$name$ = hg.h
                call e.execute()
                set hg = hg.prev
            endloop
        endif
    endmethod
        
        // clear the handle group
    method clear takes nothing returns nothing
        local $handle$group hg
        local $handle$group temp
        if (this.last!=this) then
            set hg = this.last
            loop
                exitwhen (hg==this)
                set temp = hg.prev
                set hg.last = hg
                call hg.destroy()
                set hg = temp
            endloop
        endif
    endmethod
    
    method refresh takes nothing returns nothing
        local $handle$group hg = this.last
        loop
            exitwhen (hg==this)
            if (hg.h==null) then
                call hg.unlink()
                set this.count = this.count-1
            endif
            set hg = hg.prev
        endloop
    endmethod
    
        // return the first handle of the group
    method firstOfGroup takes nothing returns $handle$
        return this.next.h
    endmethod
    
    method getRandom takes nothing returns $handle$
        local integer i = 1
        local integer rand = GetRandomInt(1, .count)
        local $handle$group hg = this.next
        loop
            exitwhen (i==rand)
            set hg = hg.next
            set i = i+1
        endloop
        return hg.h
    endmethod
        
        // return true if the handle exists in the handle group
    method isInGroup takes $handle$ h returns boolean
        local $handle$group hg
        if (h!=null) then
            set hg = this.last
            loop
                exitwhen (hg==this)
                if (hg.h==h) then
                    return true
                endif
                set hg = hg.prev
            endloop 
        endif
        return false
    endmethod
    
    method getCount takes nothing returns integer
        return this.count
    endmethod
    
        // add a handle to the handle group
    method add takes $handle$ h returns nothing
        local $handle$group hg
        if (h!=null and .isInGroup(h)==false) then
            set hg = $handle$group.allocate()
            set hg.prev = this.last
            set hg.prev.next = hg
            set this.last = hg
            set hg.h = h
            set this.count = this.count+1
        endif
    endmethod
        
        // remove a handle from the group
    method remove takes $handle$ h returns nothing
        local $handle$group hg
        if (h!=null) then
            set hg = this.next
            loop
                exitwhen (hg==this.last)
                if (hg.h==h) then
                    call hg.unlink()
                    set this.count = this.count-1
                    exitwhen (true)
                endif
                set hg = hg.next
            endloop
        endif
    endmethod
    
    static method create takes nothing returns $handle$group
        local $handle$group hg = $handle$group.allocate()
        set hg.last = hg
        return hg
    endmethod
    
    private method onDestroy takes nothing returns nothing
        local $handle$group hg
        local $handle$group temp
        if (this.last!=this) then // if the destroyed handle group is a list, depopulate it
            set hg = this.last
            loop
                exitwhen (hg==this)
                set temp = hg.prev
                call hg.destroy()
                set hg = temp
            endloop
        endif
        set this.h = null
    endmethod

endstruct

    // WC3 style functions
$scope$ function Create$name$Group takes nothing returns $handle$group
    return $handle$group.create()
endfunction
$scope$ function Destroy$name$Group takes $handle$group hg returns nothing
    call hg.destroy()
endfunction
$scope$ function Refresh$name$Group takes $handle$group hg returns nothing
    call hg.refresh()
endfunction
$scope$ function Clear$name$Group takes $handle$group hg returns nothing
    call hg.clear()
endfunction
$scope$ function $name$GroupAdd$name$ takes $handle$group hg, $handle$ h returns nothing
    call hg.add(h)
endfunction
$scope$ function $name$GroupRemove$name$ takes $handle$group hg, $handle$ h returns nothing
    call hg.remove(h)
endfunction
$scope$ function Is$name$In$name$Group takes $handle$group hg, $handle$ h returns boolean
    return hg.isInGroup(h)
endfunction
$scope$ function Count$name$sIn$name$Group takes $handle$group hg returns integer
    return hg.getCount()
endfunction
$scope$ function FirstOf$name$Group takes $handle$group hg returns $handle$
    return hg.firstOfGroup()
endfunction
$scope$ function For$name$Group takes $handle$group hg, enumfunc e returns nothing
    call hg.forGroup(e)
endfunction
//! endtextmacro

function interface enumfunc takes nothing returns nothing

endlibrary

You could have done X better.
Please, if something could be better, tell me :thup:

Change Log
v1.03
Changed some method names to make them smaller (easier to type). They're no longer explicit of what they do..but you'll manage.
Also removed an unneeded variable, thanks to J4L for pointing that out.

v1.02
Fixed a few typos. Added missing WC3 style functions. Changed the method naming convention to start with lower case. All these thanks to kenny!
Switched back to function interfaces after I realized they're simpler.

v1.01
I changed .ForGroup to use code instead of a function interface. I'm not sure why it did in the first place anyways.
 

Kenny

Back for now.
Reaction score
202
Awesome. *Gives simple praise*. It will just have to do, I lost the photos. :p

There are however some things that bug me a little (just person preference really).

1. You should just use thistype instead of all this $handle$group crap. It just looks so much 'neater', and makes it easy to change.

2. Your naming convention... Usually you see methods with the first-letter-of-the-first-word-not-capitalised-while-the-first-letter-of-the-next-word-is kind of thing. :p When working with methods, it is a strong habit of mine, and others, to start off with a small letter. But hey it's up to you.

3. You never seem to put 'this' in front of .count. Just seems a little odd (seems like it is not standardised), but you probably have your reasons.

4. You don't have a wc3 style function for Get$name$Count. (I am assuming that is the CountUnitsInGroup() function for the handlegroups.

Anywho, as I said, most of those things are just odd to me and don't really change anything to do with this system.

Great system, and it is definately useful. :thup:
 

quraji

zap
Reaction score
144
Awesome. *Gives simple praise*. It will just have to do, I lost the photos. :p

There are however some things that bug me a little (just person preference really).

1. You should just use thistype instead of all this $handle$group crap. It just looks so much 'neater', and makes it easy to change.

2. Your naming convention... Usually you see methods with the first-letter-of-the-first-word-not-capitalised-while-the-first-letter-of-the-next-word-is kind of thing. :p When working with methods, it is a strong habit of mine, and others, to start off with a small letter. But hey it's up to you.

3. You never seem to put 'this' in front of .count. Just seems a little odd (seems like it is not standardised), but you probably have your reasons.

4. You don't have a wc3 style function for Get$name$Count. (I am assuming that is the CountUnitsInGroup() function for the handlegroups.

Anywho, as I said, most of those things are just odd to me and don't really change anything to do with this system.

Great system, and it is definately useful. :thup:

Thanks for the comment.

1. Meh, I guess. I just wrote this to say "handlegroup" then search+replaced it, so it wasn't an issue for me.

2. I usually do that, but I didn't originally plan on adding the WC3 style functions so I thought I should be friendly to people who like that naming convention. I'll change it back since the WC3 functions are there.

3. Nope, you're right. I added .count in later on, so I must have forgot that my style at the time was this.member :p

4. Neither do I have one for .Refresh. Thanks for pointing that out.

Once again thanks, I always like hearing from you kenny! :thup:
 

Azlier

Old World Ghost
Reaction score
461
Two things:

1. Either make the enumfuncs be called by .evaluate (it's faster) or make them into code arguments instead, with a little magic.

2. Refresh will not work for all handle types (mainly triggers). I don't know of a good way around that.
 

Jesus4Lyf

Good Idea™
Reaction score
397
This uses a textmacro interface for unknown reasons.

It should provide simple functions for the user to deal with instead.

And I'd suggest that universally, the limit be 8190 or whatever instead of requiring the user to enter it (who needs >8190 instances of something like this). But that much is up to you.
 

quraji

zap
Reaction score
144
No real interest was shown in this (understandable), so I haven't bothered updating it with improvements/changes.

>> This uses a textmacro interface for unknown reasons.

I don't understand.

>> It should provide simple functions for the user to deal with instead.

Are you saying I should make the groups follow an interface so they can use one set of WC3 style functions?

>> And I'd suggest that universally, the limit be 8190 or whatever instead of requiring the user to enter it (who needs >8190 instances of something like this). But that much is up to you.

It probably won't be needed, but remember that these groups are actually linked lists so the usage will climb faster than if they were actual groups.
Hm, I wonder if this would be better purely using hashtables (one hashtable for each type)?
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top