lib/taskjuggler/ResourceScenario.rb in taskjuggler-3.2.0 vs lib/taskjuggler/ResourceScenario.rb in taskjuggler-3.3.0

- old
+ new

@@ -182,37 +182,29 @@ end #puts "Booking resource #{@property.fullId} at " + # "#{@scoreboard.idxToDate(sbIdx)}/#{sbIdx} for task #{task.fullId}\n" @scoreboard[sbIdx] = task - # Track the total allocated slots for this resource and all parent - # resources. - t = @property - while t - t['effort', @scenarioIdx] += 1 - t = t.parent - end + # Track the total allocated slots for this resource. + @effort += @efficiency @limits.inc(sbIdx) if @limits # Scoreboard iterations are fairly expensive but they are very frequent # operations in later processing. To limit the interations to the # relevant intervals, we store the interval for all bookings and for # each individual task. if @firstBookedSlot.nil? || @firstBookedSlot > sbIdx - @firstBookedSlot = sbIdx + @firstBookedSlot = @firstBookedSlots[task] = sbIdx + elsif @firstBookedSlots[task].nil? || @firstBookedSlots[task] > sbIdx + @firstBookedSlots[task] = sbIdx end if @lastBookedSlot.nil? || @lastBookedSlot < sbIdx - @lastBookedSlot = sbIdx + @lastBookedSlot = @lastBookedSlots[task] = sbIdx + elsif @lastBookedSlots[task].nil? || @lastBookedSlots[task] < sbIdx + @lastBookedSlots[task] = sbIdx end - if task - if @firstBookedSlots[task].nil? || @firstBookedSlots[task] > sbIdx - @firstBookedSlots[task] = sbIdx - end - if @lastBookedSlots[task].nil? || @lastBookedSlots[task] < sbIdx - @lastBookedSlots[task] = sbIdx - end - end + true end def bookBooking(sbIdx, booking) initScoreboard if @scoreboard.nil? @@ -251,10 +243,25 @@ end book(sbIdx, booking.task, true) end + # @effort only trackes the already allocated effort for leaf resources. It's + # too expensive to propagate this to the group resources on every booking. + # If a value for a group effort is needed, it's computed here. + def bookedEffort + if @property.leaf? + @effort + else + effort = 0 + @property.kids.each do |r| + effort += r.bookedEffort(@scenarioIdx) + end + effort + end + end + # Compute the annual leave days within the period specified by the # _query_. The result is in days. def query_annualleave(query) query.sortable = query.numerical = val = getLeave(query.startIdx, query.endIdx, :annual) @@ -294,10 +301,35 @@ query.sortable = query.numerical = effort = getEffectiveWork(query.startIdx, query.endIdx, query.scopeProperty) query.string = query.scaleLoad(effort) end + # The completed (as of 'now') effort allocated for the resource in the + # specified interval. In case a Task is given as scope property only + # the effort allocated for this Task is taken into account. + def query_effortdone(query) + # For this query, we always override the query period. + query.sortable = query.numerical = effort = + getEffectiveWork(@project.dateToIdx(@project['start'], false), + @project.dateToIdx(@project['now']), + query.scopeProperty) + query.string = query.scaleLoad(effort) + end + + + # The remaining (as of 'now') effort allocated for the resource in the + # specified interval. In case a Task is given as scope property only + # the effort allocated for this Task is taken into account. + def query_effortleft(query) + # For this query, we always override the query period. + query.sortable = query.numerical = effort = + getEffectiveWork(@project.dateToIdx(@project['now']), + @project.dateToIdx(@project['end'], false), + query.scopeProperty) + query.string = query.scaleLoad(effort) + end + # The unallocated work time of the Resource during the specified interval. def query_freetime(query) query.sortable = query.numerical = time = getEffectiveFreeTime(query.startIdx, query.endIdx) / (60 * 60 * 24) query.string = query.scaleDuration(time) @@ -447,13 +479,14 @@ # Make sure we have the real Task and not a proxy. task = task.ptn if task # There can't be any effective work if the start is after the end or the # todo list doesn't contain the specified task. return 0.0 if startIdx >= endIdx || (task && !@duties.include?(task)) + # Temporary workaround until @duties is fixed again. # The unique key we use to address the result in the cache. - @dCache.cached(self, :ResourceScenarioEffectiveWork, startIdx, endIdx, + @dCache.cached(self, :ResourceScenarioGetEffectiveWork, startIdx, endIdx, task) do work = 0.0 if @property.container? @property.kids.each do |resource| work += resource.getEffectiveWork(@scenarioIdx, startIdx, endIdx, @@ -514,17 +547,17 @@ amount += child.turnover(@scenarioIdx, startIdx, endIdx, account, task) end else if task - # If we have a know task, we only include the amount that is + # If we have a known task, we only include the amount that is # specific to this resource, this task and the chargeset of the # task. amount += task.turnover(@scenarioIdx, startIdx, endIdx, account, @property) elsif !@chargeset.empty? # If no tasks was provided, we include the amount of this resource, - # weighted by the charset of this resource. + # weighted by the chargeset of this resource. totalResourceCost = cost(startIdx, endIdx) @chargeset.each do |set| set.each do |accnt, share| if share > 0.0 && (accnt == account || accnt.isChildOf?(account)) amount += totalResourceCost * share