Class: TaskJuggler::Allocation

Inherits:
Object
  • Object
show all
Defined in:
lib/taskjuggler/Allocation.rb

Overview

The Allocation is key object in TaskJuggler. It contains a description how Resources are assigned to a Task. Each allocation holds a non-empty list of candidate resources. For each time slot one candidate will be assigned if any are available. A selectionMode controls the order in which the resources are checked for availability. The first available one is selected.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(candidates, selectionMode = 1, persistent = false, mandatory = false, atomic = false) ⇒ Allocation

Create an Allocation object. The candidates list must at least contain one Resource reference.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/taskjuggler/Allocation.rb', line 32

def initialize(candidates, selectionMode = 1, persistent = false,
               mandatory = false, atomic = false)
  @candidates = candidates
  # The selection mode determines how the candidate is selected from the
  # list of candidates.
  # 0 : 'order'        : select by order of list
  # 1 : 'minallocated' : select candidate with lowest allocation
  #                      probability
  # 2 : 'minloaded'    : select candidate with lowest allocated overall
  #                      load
  # 3 : 'maxloaded'    : select candidate with highest allocated overall
  #                      load
  # 4 : 'random'       : select a random candidate
  @selectionMode = selectionMode
  @atomic = atomic
  @persistent = persistent
  @mandatory = mandatory
  @shifts = nil
  @staticCandidates = nil
end

Instance Attribute Details

#atomicObject

Returns the value of attribute atomic.



28
29
30
# File 'lib/taskjuggler/Allocation.rb', line 28

def atomic
  @atomic
end

#lockedResourceObject

Returns the value of attribute lockedResource.



28
29
30
# File 'lib/taskjuggler/Allocation.rb', line 28

def lockedResource
  @lockedResource
end

#mandatoryObject

Returns the value of attribute mandatory.



28
29
30
# File 'lib/taskjuggler/Allocation.rb', line 28

def mandatory
  @mandatory
end

#persistentObject

Returns the value of attribute persistent.



28
29
30
# File 'lib/taskjuggler/Allocation.rb', line 28

def persistent
  @persistent
end

#selectionModeObject (readonly)

Returns the value of attribute selectionMode.



27
28
29
# File 'lib/taskjuggler/Allocation.rb', line 27

def selectionMode
  @selectionMode
end

#shiftsObject

Returns the value of attribute shifts.



28
29
30
# File 'lib/taskjuggler/Allocation.rb', line 28

def shifts
  @shifts
end

Instance Method Details

#addCandidate(candidate) ⇒ Object

Append another candidate to the candidates list.



62
63
64
# File 'lib/taskjuggler/Allocation.rb', line 62

def addCandidate(candidate)
  @candidates << candidate
end

#candidates(scenarioIdx = nil) ⇒ Object

Return the candidate list sorted according to the selectionMode.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/taskjuggler/Allocation.rb', line 75

def candidates(scenarioIdx = nil)
  # In case we have selection criteria that results in a static list, we
  # can use the previously determined list.
  return @staticCandidates if @staticCandidates

  if scenarioIdx.nil? || @selectionMode == 0 # declaration order
    return @candidates
  end

  if @selectionMode == 4 # random
    # For a random sorting we put the candidates in a hash with a random
    # number as key. Then we sort the hash according to the random keys an
    # use the resuling sequence of the values.
    hash = {}
    @candidates.each { |c| hash[rand] = c }
    twinList = hash.sort { |x, y| x[0] <=> y[0] }
    list = []
    twinList.each { |k, v| list << v }
    return list
  end

  list = @candidates.sort do |x, y|
    case @selectionMode
    when 1 # lowest alloc probability
      if @persistent
        # For persistent resources we use a more sophisticated heuristic
        # than just the criticalness of the resource. Instead, we
        # look at the already allocated slots of the resource. This will
        # reduce the probability to pick a persistent resource that was
        # already allocated for a higher priority or more critical task.
        if (cmp = x.bookedEffort(scenarioIdx) <=>
                  y.bookedEffort(scenarioIdx)) == 0
          x['criticalness', scenarioIdx] <=> y['criticalness', scenarioIdx]
        else
          cmp
        end
      else
        x['criticalness', scenarioIdx] <=> y['criticalness', scenarioIdx]
      end
    when 2 # lowest allocated load
      x.bookedEffort(scenarioIdx) <=> y.bookedEffort(scenarioIdx)
    when 3 # hightes allocated load
      y.bookedEffort(scenarioIdx) <=> x.bookedEffort(scenarioIdx)
    else
      raise "Unknown selection mode #{@selectionMode}"
    end
  end

  @staticCandidates = list if @selectionMode == 1 && !@persistent

  list
end

#onShift?(sbIdx) ⇒ Boolean

Returns true if we either have no shifts defined or the defined shifts are active at date specified by global scoreboard index sbIdx.

Returns:

  • (Boolean)


68
69
70
71
72
# File 'lib/taskjuggler/Allocation.rb', line 68

def onShift?(sbIdx)
  return @shifts.onShift?(sbIdx) if @shifts

  true
end

#setSelectionMode(str) ⇒ Object

Set the selection mode identified by name specified in str. For efficiency reasons, we turn the name into an Integer value.



55
56
57
58
59
# File 'lib/taskjuggler/Allocation.rb', line 55

def setSelectionMode(str)
  modes = %w( order minallocated minloaded maxloaded random )
  @selectionMode = modes.index(str)
  raise "Unknown selection mode #{str}" if @selectionMode.nil?
end