Snippet Field

Executor

I see you
Reaction score
57
Field
v1.03
made by Executor​

I mainly wrote this component for the system I'm developing in moment. But why not share what I have?

What does my "Field" do?
Well primarily this Struct is able to store values [of any kind] in a list (you always add values to the end) to later on regain them stepwise. It is also able to delete specific values, to check wether a value is in the 'Field' or not, to determine similarities between 'Fields' and more.

Using other types instead of integer:
JASS:
// If you want to use other types instead of integer go to the top of the code
// and add 
//! runtextmacro Field("TypeName","ContainedType","NullValue")
// for ex. :
//! runtextmacro Field("IntField","integer","-1")
//! runtextmacro Field("TimField","timer","null")
//! runtextmacro Field("TrigField","trigger","null")
//! runtextmacro Field("UnitField","unit","null")

// but these are only EXAMPLES you can name the Field as you wish (for ex. : local bla blubb = bla.create())

// Note that adding other types than integer will require to delete the .visualize debug method.

Interface:
JASS:

// Field Interface:

// Static Methods (TypeName.MethodName(Parameters):returnValue)

// .create : Type
// Returns a new empy instance of the type

// .similarities(Field1,Field2,boolean allowDupe) : Type
// Returns a new instance of the type filled with the common denominators of the 2 fields
// If 'allowDupe' is true the returned field will contain the common denominators as often as they exist

// Standard Methods (TypeInstance.MethodName(Parameters):returnValue)

// .empty : boolean
// Is Field empty?

// .contains(value) : boolean
// Does the Field already contain this 'value' ?

// .countValue(value) : integer
// Exitsts the value more often than once in the Field, if yes how many?

// .add(value)
// appends the new value to the end of the Field

// .take : value
// returns and deletes the first value in the Field

// .read : value
// returns the first value in the Field

// .size : integer
// returns size of the Field

// .deleteValue(value, boolean all)
// if the value exists in the list.. delete it! if 'all' = true delete every instance containing this value and not only one.

// .combine(Field2)
// adds 'Field2' to the calling Field Instance and clears 'Field2'

// .addField(Field2)
// adds 'Field2' to the calling Field

// .shuffle()
// randomizes the order of the values in the list

// .subtractField(Field2)
// deletes all members of Field1 found in Found2

// .unDupe()
// if values exist 2 or more times in a field .. delete all except one

// .getDupe(boolean allowdupe) : Type
// if values exist 2 or more times in a field .. return them in a Field and if allowdupe is true return them as often as they exist in the calling Field

// .clear
// clears the calling Field Instance

// debug .visualize() : string
// returns the Field, for ex.: [1,6,4,8,5,4]


Demo:
JASS:
scope FieldTest initializer Testinit
    private function Test1 takes nothing returns nothing
        local IntField Field = IntField.create()
        
        call Field.add(1)
        call Field.add(2)
        call Field.add(3)
        
        call Field.add(1)
        call Field.add(2)
        call Field.add(3)
        
        call Field.add(3)
        call Field.add(2)
        call Field.add(1)
        // => [1,2,3, 1,2,3, 3,2,1]
        
        call Field.deleteValue(3,false)
        // => [1,2, 1,2,3, 3,2,1]
        
        call Field.deleteValue(3,true)
        // => [1,2, 1,2, 2,1]
        
        if Field.contains(3) then // => false
            call BJDebugMsg("Field contains '3'")
        else
            call BJDebugMsg("Field does not contain '3'")
        endif
        
        call BJDebugMsg("Count '3': "+ I2S(Field.countValue(3)))
        // => 0
        
        call BJDebugMsg("Count '3': "+ I2S(Field.countValue(1)))
        // => 3
        
        // ==
        // [1,2, 1,2, 2,1]
        // == 
        
        call BJDebugMsg("Read: "+I2S(Field.read()))
        // => 1
        
        call BJDebugMsg("Take: "+I2S(Field.take()))
        // => 1
        
        call BJDebugMsg("Size: "+I2S(Field.size()))
        // => 5
        
        call BJDebugMsg("Read: "+I2S(Field.read()))
        call BJDebugMsg("Read: "+I2S(Field.read()))
        call BJDebugMsg("Read: "+I2S(Field.read()))
        // => 2 .... 2 ..... 2
        
        call BJDebugMsg("Take: "+I2S(Field.take()))
        call BJDebugMsg("Take: "+I2S(Field.take()))
        call BJDebugMsg("Take: "+I2S(Field.take()))
        // => 2 .... 1 ..... 2
        
        call BJDebugMsg("Size: "+I2S(Field.size()))
        // => 2
        
        call Field.destroy()
    endfunction    
    
    private function Test2 takes nothing returns nothing
        local IntField FieldA = IntField.create()
        local IntField FieldB = IntField.create()
        local IntField FieldS
        
        call FieldA.add(1)
        call FieldA.add(5)
        call FieldA.add(3)
        // => [1,5,3]
        
        call FieldB.add(3)
        call FieldB.add(1)
        call FieldB.add(1)
        // => [3,1,1]
        
        set FieldS = IntField.similarities(FieldA,FieldB,true)
        // => [1,1,3]
        
        call FieldS.destroy()
        
        set FieldS = IntField.similarities(FieldA,FieldB,false)
        // => [1,3]
        
        call FieldA.combine(FieldB)
        // => [1,5,3, 3,1,1]
        
        call BJDebugMsg("Size A: " + I2S(FieldA.size()))
        // => 6 
        // => [1,2,3, 6,7,8]
        
        call BJDebugMsg("Size B: " + I2S(FieldB.size()))
        // => 0
        // => []
        
        call FieldA.destroy()
        call FieldB.destroy()
    endfunction
    private function Testinit takes nothing returns nothing
        call Test1.execute()
        call Test2.execute()
    endfunction
endscope

Code:
JASS:
library Field 
    globals
        private constant integer Null = -1
    endglobals
    
//! runtextmacro Field("IntField","integer","-1")     
    
//! textmacro Field takes NAME TYPE NULL
    struct $NAME$   
        $NAME$List f
        $NAME$List l
        
        static method create takes nothing returns thistype
            local thistype this = .allocate()
            set .f = Null
            set .l = Null
            return this        
        endmethod
        
        method empty takes nothing returns boolean
            return .f == Null
        endmethod
        
        method contains takes $TYPE$ v returns boolean
            local $NAME$List l = .f
            loop
                exitwhen l == Null
                if l.v == v then
                    return true
                endif
                set l = l.n
            endloop
            return false
        endmethod
        
        method countValue takes $TYPE$ v returns integer
            local $NAME$List l = .f
            local integer    c = 0
            loop
                exitwhen l == Null
                if l.v == v then
                    set c = c + 1
                endif
                set l = l.n
            endloop
            return c
        endmethod
        
        method addLast takes $TYPE$ v returns nothing
            if .l == Null then
                set .f = $NAME$List.create(this,v)
                set .l = .f
            else
                set .l = .l.addLast(v)
            endif
        endmethod
        
        method addFirst takes $TYPE$ v returns nothing
            if .f == Null then
                set .f = $NAME$List.create(this,v)
                set .l = .f
            else
                set .f = .l.addFirst(v)
            endif
        endmethod
        
        method takeLast takes nothing returns $TYPE$ 
            local $TYPE$ v = $NULL$
            if .l != Null then
                set v = .l.v
                call .remove(.l)
            endif
            return v
        endmethod
        
        method takeFirst takes nothing returns $TYPE$ 
            local $TYPE$ v = $NULL$
            if .f != Null then
                set v = .f.v
                call .remove(.f)
            endif
            return v
        endmethod
        
        method read takes nothing returns $TYPE$
            return .f.v
        endmethod
        
        method size takes nothing returns integer
        // could be replaced with a variable if its needed often
            local integer  c = 0
            local $NAME$List l = .f
            loop
                exitwhen l == Null
                set l = l.n
                set c = c + 1
            endloop
            return c        
        endmethod
        
        method deleteValue takes $TYPE$ v, boolean all returns nothing
            local $NAME$List l = .f
            loop
                exitwhen l == Null
                if l.v == v then
                    set l = l.n
                    call .remove(l.l)
                    if not all then
                        return
                    endif
                else
                    set l = l.n
                endif
            endloop    
        endmethod

        method combine takes thistype o returns nothing
            if not o.empty() then
                set o.f.l = .l
                set .l.n = o.f
                set o.f = Null
                set o.l = Null
            endif
        endmethod 
        
        method shuffle takes nothing returns nothing
            local $TYPE$ array p
            local integer      m = 0
            local $NAME$List   l = .f
            local integer      r = 0
            loop
                exitwhen l == Null
                set p[m] = l.v
                set m    = m +1
                set l    = l.n
            endloop
            set l = .f
            loop
                exitwhen (m <= 0) or (l == Null)
                set r      = GetRandomInt(0,m-1)
                set l.v    = p[r]
                set p[r]   = p[m-1]
                set p[m-1] = $NULL$
                set m      = m -1
                set l = l.n
            endloop                  
        endmethod
        
        method subtractField takes thistype o returns nothing
            local $NAME$List g = o.f
            local $NAME$List l = Null
            local $NAME$List b = Null
            loop
                exitwhen g == Null
                set l = .f
                loop
                    exitwhen l == Null
                    if l.v == g.v then
                        set b = l
                    endif
                    set l = l.n
                    if b != Null then
                        call .remove(b)
                    endif
                endloop
                set g = g.n
            endloop
        endmethod
        
        method addField takes thistype o returns nothing 
            local $NAME$List l = o.f
            loop
                exitwhen l == Null
                call .add(l.v)
                set l = l.n
            endloop 
        endmethod
        
        method unDupe takes nothing returns nothing
            local $NAME$List g = .f
            local $NAME$List l = Null
            local $NAME$List b = Null
            loop
                exitwhen g == Null
                set l = g.n
                loop
                    exitwhen l == Null
                    if l.v == g.v then
                        set b = l
                    endif
                    set l = l.n
                    if b != Null then
                        call .remove(b)
                    endif
                endloop
                set g = g.n
            endloop
        endmethod
        
        method getDupe takes boolean allowdupe returns thistype
            local thistype new = thistype.create()
            local $NAME$List l = .f
            local integer    i = 0
            local integer    m = 0
            loop
                exitwhen l == Null
                if not new.contains(l.v) then
                    set m = .countValue(l.v)
                    if m > 1 then
                        if (m > 2) and allowdupe then
                            set i = 1
                            loop
                                exitwhen m <= i
                                call new.add(l.v)   
                                set i = i + 1
                            endloop
                        else
                            call new.add(l.v)
                        endif
                    endif
                endif
                set l = l.n
            endloop
            return new
        endmethod
        
        static method similarities takes thistype a, thistype o, boolean allowdupe returns thistype
            local thistype new = thistype.create()
            local $TYPE$   v   = $NULL$
            local integer m = a.size()
            local integer i = 0
            local integer n = 0
            local integer j = 0
            loop
                exitwhen i >= m
                set v = a.take()
                set n = o.countValue(v) 
                if n >= 1 then
                    if allowdupe then
                        set j = 0
                        loop
                            exitwhen j >= n
                            call new.add(v)
                            set j = j + 1
                        endloop
                    else
                        call new.add(v)
                    endif                        
                endif
                call a.add(v)
                set i = i + 1
            endloop 
            return new
        endmethod
        
        method clear takes nothing returns nothing
            local $NAME$List l = .f
            if .f == Null then
                return
            endif
            loop
                exitwhen l.n == Null
                set l = l.n
                call .remove(l.l)
            endloop
            call .remove(l)            
        endmethod
        
        debug method visualize takes nothing returns string
        debug     local string     s = "["
        debug     local $NAME$List l = .f            
        debug     loop
        debug         exitwhen l == Null
        debug         set s = s + I2S(l.v)
        debug         if l.n != Null then
        debug             set s = s + ","
        debug         endif
        debug         set l = l.n
        debug     endloop
        debug     set s = s + "]"
        debug     return s
        debug endmethod
        
        private method remove takes $NAME$List r returns nothing
            if r == Null then
                return
            elseif r == .f then
                set .f = r.n
            endif
            if r == .l then
                set .l = r.l
            endif
            call r.remove()
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call .clear()
        endmethod
        
        method take takes nothing returns $TYPE$
            return .takeFirst()
        endmethod
        
        method add takes $TYPE$ v returns nothing
            call .addLast(v)
        endmethod
    endstruct
    
    struct $NAME$List
        thistype n
        thistype l
        $TYPE$   v
    
        static method create takes $NAME$ p, $TYPE$ v returns thistype
            local thistype this = thistype.allocate()
            set .n = Null
            set .l = Null
            set .v = v
            return this
        endmethod
        
        method addLast takes $TYPE$ v returns thistype
            local thistype new = thistype.allocate() 
            set new.n = Null
            set new.l = this
            set new.v = v
            set .n    = new
            return new
        endmethod
        
        method addFirst takes $TYPE$ v returns thistype
            local thistype new = thistype.allocate()
            set new.n = this
            set new.l = Null
            set new.v = v
            set .l    = new
            return new
        endmethod
        
        method remove takes nothing returns nothing
            if .l != Null then
                set .l.n = .n
            endif
            if .n != Null then
                set .n.l = .l
            endif
            set .v = $NULL$
       endmethod
    endstruct
    //! endtextmacro
endlibrary

Changelog:
09-24-2009: v 1.00 Initial Release
09-24-2009: v 1.01 Initial Release ["addField" and "combine" optimized; deleted parent connection between list and field]
09-25-2009: v 1.02 Initial Release ["subtractField";"front add";"back take";"shuffle";"unDupe";"getDupe" added]

To Do List:
  • alternative for determing 'size' in 'add' and 'remove' process
  • optimize code
  • deleting all typos :)


Credits to Romek for inspiring me with his queue.

I'm always happy about feedback and/or criticism, it all shall help my code become more efficient ;)
 

Hatebreeder

So many apples
Reaction score
381
When does something queue up?

For instance:
Value1 and Value2 is created.
you check in a timer if Value1 reches a certain value. As soon as it hits that value you want Value2 to be valid. How would I be able to do that?
 

Romek

Super Moderator
Reaction score
963
> Rather than creating a new, why don't you just suggest him to do it?
This. Not to mention that I actually had adding methods like this to queue on my to-do list. =|

In fact, after completely reading through the method list, I notice that I was going to add just about ALL of those methods.
As well as make queue double-ended.

sigh
I really dislike it when people to this.
 

Executor

I see you
Reaction score
57
Well in fact I didn't want to steal your idea, but I was in need of this component and HAD to write it ..
If you wish I can delete this publication, because you of course have the rights on the basis of my component.
I just thought you want to stick to a basic queue and not overcomplicate as I did.

Rather than creating a new, why don't you just suggest him to do it?

Because it really needed a high amount of enhancement to be capable dealing with my problem.

When does something queue up?

For instance:
Value1 and Value2 is created.
you check in a timer if Value1 reches a certain value. As soon as it hits that value you want Value2 to be valid. How would I be able to do that?

Could you explain your problem a little bit further? I don't really get your point.
 

Trollvottel

never aging title
Reaction score
262
A O(n) list add :/ couldnt you just make it O(1)? I just dont really like too much looping
 

Romek

Super Moderator
Reaction score
963
> Because it really needed a high amount of enhancement to be capable dealing with my problem.
Based on the functions that you added, it doesn't look as though that's the case.

Anyway, queue should have all (most) of these later today.
 

Renendaru

(Evol)ution is nothing without love.
Reaction score
309
Sigh, I had ALL of these methods in a list already, and even more methods as well. It uses Linked Lists atm, it's basically a clean interface to Linked Lists. I've had it made for over a month now, just never felt to submit it.
 

quraji

zap
Reaction score
144
Why is everyone getting their panties in a bunch? I thought this was the resources submission. I don't see anything wrong with competing systems/snippets. May the best one win and be moved into resources, the other is graveyarded indefinitely or until it's better than the other? Right?

I guess the only problem is if someone decides to use one and another becomes better, and there's no standard. So, more standards? :)
I like competition.
 

Romek

Super Moderator
Reaction score
963
Oh, there's nothing wrong with 'competition'.
It's just that when somebody goes:
"Oh, this jump system can't jump to location!"
*Copy + Pastes, adds JumpToLoc function, and submits new system*

Wouldn't a comment asking for a new function would've been better? :rolleyes:
 

Executor

I see you
Reaction score
57
A O(n) list add :/ couldnt you just make it O(1)? I just dont really like too much looping

Couldn't really allocate wether you meant a specific method or all loops, but I hope I fixed it with my update ;)

Oh, there's nothing wrong with 'competition'.
It's just that when somebody goes:
"Oh, this jump system can't jump to location!"
*Copy + Pastes, adds JumpToLoc function, and submits new system*

Wouldn't a comment asking for a new function would've been better? :rolleyes:

I didn't copy anything. In fact I wrote all myself and well I think quraji is right: Let the forum members decide, which system they want to use.

And if a mod thinks I copied anything (which is not self-evident solving this kind of problem) he can still delete my post.
 

Romek

Super Moderator
Reaction score
963
As it stands now, I'm not going to delete anything, and of course users will have to pick which they prefer. Just for a future note, if you think a system would be better off with a certain function, go tell the creator.

Note: I've added everything I wanted to, to Queue.
 

Trollvottel

never aging title
Reaction score
262
JASS:
        method addField takes thistype o returns nothing 
            local $NAME$List l = o.f
            loop
                exitwhen l == Null
                call .add(l.v)
                set l = l.n
            endloop 
        endmethod


i mean this one.

you do it with loops, but couldnt you just change some links? i will try to make an example:

In List 1:
O1-O2-O3

In List 2:
O4-O5-O6

now you put out the values from list 2 and put them into list 1 but:

you could just change the pointer of O3 to point to O4. this points to O5 which points to O6, so you have the whole list added with one set (of course the are other things to be done).
 

Executor

I see you
Reaction score
57
JASS:
        method addField takes thistype o returns nothing 
            local $NAME$List l = o.f
            loop
                exitwhen l == Null
                call .add(l.v)
                set l = l.n
            endloop 
        endmethod


i mean this one.

you do it with loops, but couldnt you just change some links? i will try to make an example:

In List 1:
O1-O2-O3

In List 2:
O4-O5-O6

now you put out the values from list 2 and put them into list 1 but:

you could just change the pointer of O3 to point to O4. this points to O5 which points to O6, so you have the whole list added with one set (of course the are other things to be done).

Yes but its the tenor of the method 'addField' to retain the original Field of the parameter.

The technique you mention is used in the method 'combine' which clears the parameter Field.

JASS:
        method combine takes thistype o returns nothing
            if not o.empty() then
                set o.f.l = .l // the dual connection between knots
                set .l.n = o.f // ~
                set o.f = Null // clear Field o
                set o.l = Null // clear Field o
            endif
        endmethod 
        
        method addField takes thistype o returns nothing 
            local $NAME$List l = o.f
            loop
                exitwhen l == Null
                call .add(l.v)
                set l = l.n
            endloop 
        endmethod


Just for a future note, if you think a system would be better off with a certain function, go tell the creator.

Well as Renendaru already mentioned the idea of a "queue", a "Field" or however to call it isn't very unique.. I know programming languages, which contains basicly comparable types. You are 'just' the one, who publicated this kind of component first.
But nevertheless I understand your infuriation and apologize for my rude behaviour.
 

Jesus4Lyf

Good Idea™
Reaction score
397
This is the standard linked list implementation.

If this has functionality which cannot be achieved with that implementation, please state so.
  • If it can be achieved in that implementation, we'll ask for it to be updated.
  • If indeed it can never be achieved with that implementation, we will approve an alternative (so long as it is practical).

You have to understand from a moderating point of view, we don't intend on approving 2 or 3 different linked list implementations without some kind of reason.

I expect Queue to be graveyarded (but that will, of course, depend on the functionality).
 

Executor

I see you
Reaction score
57
Well it IS definitly possible to use this standard linked list implementation for my component, BUT why?

Using this implemenation will lead to
  • non-fitting method names or wrappers for the given methods
  • no performance enhancement (as far as I'm able to analyse the speed)
  • 'senseless' extra work for me (in case you can't explain me WHY it should be better)
  • making my snippet dependent to 3rd party systems
 

Jesus4Lyf

Good Idea™
Reaction score
397
I wasn't asking you to modify your snippet.

I was asking if your snippet should exist, considering we already have that standard implementation.

And hence, was asking you to use that instead in whatever system you intend to release instead of this.

>we'll ask for it to be updated.
"it" being the module.
 

Executor

I see you
Reaction score
57
Yes. Basically, i just wanted to know if one can choose the point at which the variables are queued up.

New knots are always added to the end, but I will maybe add an option to add them in front to.

I wasn't asking you to modify your snippet.

I was asking if your snippet should exist, considering we already have that standard implementation.

And hence, was asking you to use that instead in whatever system you intend to release instead of this.

>we'll ask for it to be updated.
"it" being the module.

Ah k misunderstanding..
Well ofc basically my component IS a linked list, but it's rubbish to update the linked list module to contain methods I or Romek have/has, because normally when using a linked list the extensions my system comprises would be obsolete.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>but it's rubbish to update the linked list module to contain methods I or Romek have/has
It's rubbish to even use any of these implementations. There's to advantage to the modularity, realistically speaking.

The linked list module recycles struct ids well and doesn't require an extra array read in loading the structs, which is nice at least. I'd still be inclined to copy/paste/modify anyway.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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