Executor
I see you
- Reaction score
- 57
Field
v1.03
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 039;3039;")
else
call BJDebugMsg("Field does not contain 039;3039;")
endif
call BJDebugMsg("Count 039;3039;: "+ I2S(Field.countValue(3)))
// => 0
call BJDebugMsg("Count 039;3039;: "+ 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