### Home Classes Methods

### In Files

- lib/taskjuggler/Project.rb

### Parent

Object

### Methods

- ::maxScheduleGranularity
- ::new
- #[]
- #[]=
- #account
- #anyResourceAvailable?
- #attributeName
- #checkReports
- #checkTimeSheets
- #collectTimeOffIntervals
- #convertToDailyLoad
- #dailyWorkingHours
- #dateToIdx
- #deep_clone
- #enableTraceReports
- #finishScenario
- #generateReport
- #generateReports
- #getWorkSlots
- #hasWorkingTime
- #idxToDate
- #isWorkingTime
- #journal
- #listReports
- #monthlyWorkingDays
- #prepareScenario
- #report
- #reportByName
- #resource
- #scenario
- #scenarioCount
- #scenarioIdx
- #schedule
- #scheduleScenario
- #scoreboardSize
- #shift
- #slotsToDays
- #task
- #to_s
- #weeklyWorkingDays
- #workingDays
- #yearlyWorkingDays

### Included Modules

- TaskJuggler::MessageHandler

### Files

- CHANGELOG
- COPYING
- README.rdoc

### Class/Module Index

Quicksearch

- TaskJuggler
- TaskJuggler::Account
- TaskJuggler::AccountAttribute
- TaskJuggler::AccountCredit
- TaskJuggler::AccountCreditListAttribute
- TaskJuggler::AccountListRE
- TaskJuggler::AccountScenario
- TaskJuggler::AlertLevelDefinition
- TaskJuggler::AlertLevelDefinitions
- TaskJuggler::Allocation
- TaskJuggler::AllocationAttribute
- TaskJuggler::AttributeBase
- TaskJuggler::AttributeDefinition
- TaskJuggler::AttributeOverwrite
- TaskJuggler::BatchProcessor
- TaskJuggler::Booking
- TaskJuggler::BookingListAttribute
- TaskJuggler::BooleanAttribute
- TaskJuggler::CSVFile
- TaskJuggler::CellSettingPattern
- TaskJuggler::CellSettingPatternList
- TaskJuggler::Charge
- TaskJuggler::ChargeListAttribute
- TaskJuggler::ChargeSet
- TaskJuggler::ChargeSetListAttribute
- TaskJuggler::ChartPlotter
- TaskJuggler::ChartPlotterError
- TaskJuggler::CollisionDetector
- TaskJuggler::ColumnListAttribute
- TaskJuggler::ColumnTable
- TaskJuggler::Daemon
- TaskJuggler::DaemonConnector
- TaskJuggler::DaemonConnectorMixin
- TaskJuggler::DataCache
- TaskJuggler::DataCacheEntry
- TaskJuggler::DateAttribute
- TaskJuggler::DefinitionListAttribute
- TaskJuggler::DependencyListAttribute
- TaskJuggler::DurationAttribute
- TaskJuggler::ExportRE
- TaskJuggler::FileList
- TaskJuggler::FileRecord
- TaskJuggler::FixnumAttribute
- TaskJuggler::FlagListAttribute
- TaskJuggler::FloatAttribute
- TaskJuggler::FormatListAttribute
- TaskJuggler::GanttChart
- TaskJuggler::GanttContainer
- TaskJuggler::GanttHeader
- TaskJuggler::GanttHeaderScaleItem
- TaskJuggler::GanttLine
- TaskJuggler::GanttLoadStack
- TaskJuggler::GanttMilestone
- TaskJuggler::GanttRouter
- TaskJuggler::GanttTaskBar
- TaskJuggler::HTMLDocument
- TaskJuggler::HTMLElements
- TaskJuggler::HTMLGraphics
- TaskJuggler::ICalReport
- TaskJuggler::ICalendar
- TaskJuggler::ICalendar::Component
- TaskJuggler::ICalendar::Event
- TaskJuggler::ICalendar::Journal
- TaskJuggler::ICalendar::Person
- TaskJuggler::ICalendar::Todo
- TaskJuggler::Interval
- TaskJuggler::IntervalList
- TaskJuggler::JobInfo
- TaskJuggler::Journal
- TaskJuggler::JournalEntry
- TaskJuggler::JournalEntryList
- TaskJuggler::JournalSortListAttribute
- TaskJuggler::KateSyntax
- TaskJuggler::KeywordArray
- TaskJuggler::KeywordDocumentation
- TaskJuggler::Leave
- TaskJuggler::LeaveAllowance
- TaskJuggler::LeaveAllowanceList
- TaskJuggler::LeaveAllowanceListAttribute
- TaskJuggler::LeaveList
- TaskJuggler::LeaveListAttribute
- TaskJuggler::Limits
- TaskJuggler::Limits::Limit
- TaskJuggler::LimitsAttribute
- TaskJuggler::ListAttributeBase
- TaskJuggler::Log
- TaskJuggler::LogicalAttribute
- TaskJuggler::LogicalExpression
- TaskJuggler::LogicalExpressionAttribute
- TaskJuggler::LogicalExpressionListAttribute
- TaskJuggler::LogicalFlag
- TaskJuggler::LogicalFunction
- TaskJuggler::LogicalOperation
- TaskJuggler::ManagerResponsibilities
- TaskJuggler::ManagerStatusRecord
- TaskJuggler::Message
- TaskJuggler::MessageHandler
- TaskJuggler::MessageHandlerInstance
- TaskJuggler::MspXmlRE
- TaskJuggler::Navigator
- TaskJuggler::NavigatorElement
- TaskJuggler::NikuProject
- TaskJuggler::NikuReport
- TaskJuggler::NikuResource
- TaskJuggler::NodeListAttribute
- TaskJuggler::PTNProxy
- TaskJuggler::Painter
- TaskJuggler::Painter::Circle
- TaskJuggler::Painter::Color
- TaskJuggler::Painter::Element
- TaskJuggler::Painter::Ellipse
- TaskJuggler::Painter::FontMetrics
- TaskJuggler::Painter::FontMetricsData
- TaskJuggler::Painter::Group
- TaskJuggler::Painter::Line
- TaskJuggler::Painter::Points
- TaskJuggler::Painter::PolyLine
- TaskJuggler::Painter::Primitives
- TaskJuggler::Painter::Rect
- TaskJuggler::Painter::SVGSupport
- TaskJuggler::Painter::Text
- TaskJuggler::PlaceHolderCell
- TaskJuggler::ProcessIntercom
- TaskJuggler::ProcessIntercomIface
- TaskJuggler::Project
- TaskJuggler::ProjectBroker
- TaskJuggler::ProjectBrokerIface
- TaskJuggler::ProjectFileParser
- TaskJuggler::ProjectFileScanner
- TaskJuggler::ProjectRecord
- TaskJuggler::ProjectServer
- TaskJuggler::ProjectServerIface
- TaskJuggler::PropertyAttribute
- TaskJuggler::PropertyList
- TaskJuggler::PropertySet
- TaskJuggler::PropertyTreeNode
- TaskJuggler::Query
- TaskJuggler::RTFHandlers
- TaskJuggler::RTFNavigator
- TaskJuggler::RTFQuery
- TaskJuggler::RTFReport
- TaskJuggler::RTFReportLink
- TaskJuggler::RTFWithQuerySupport
- TaskJuggler::RealFormat
- TaskJuggler::RealFormatAttribute
- TaskJuggler::ReferenceAttribute
- TaskJuggler::Report
- TaskJuggler::ReportBase
- TaskJuggler::ReportContext
- TaskJuggler::ReportScenario
- TaskJuggler::ReportServer
- TaskJuggler::ReportServerIface
- TaskJuggler::ReportServerRecord
- TaskJuggler::ReportServlet
- TaskJuggler::ReportTable
- TaskJuggler::ReportTableCell
- TaskJuggler::ReportTableColumn
- TaskJuggler::ReportTableLegend
- TaskJuggler::ReportTableLine
- TaskJuggler::Resource
- TaskJuggler::ResourceListAttribute
- TaskJuggler::ResourceListRE
- TaskJuggler::ResourceScenario
- TaskJuggler::RichText
- TaskJuggler::RichTextAttribute
- TaskJuggler::RichTextDocument
- TaskJuggler::RichTextElement
- TaskJuggler::RichTextFunctionExample
- TaskJuggler::RichTextFunctionHandler
- TaskJuggler::RichTextImage
- TaskJuggler::RichTextIntermediate
- TaskJuggler::RichTextParser
- TaskJuggler::RichTextScanner
- TaskJuggler::RichTextSnip
- TaskJuggler::RichTextSyntaxRules
- TaskJuggler::Scenario
- TaskJuggler::ScenarioData
- TaskJuggler::ScenarioListAttribute
- TaskJuggler::Scoreboard
- TaskJuggler::ScoreboardInterval
- TaskJuggler::SheetHandlerBase
- TaskJuggler::SheetReceiver
- TaskJuggler::SheetSender
- TaskJuggler::Shift
- TaskJuggler::ShiftAssignment
- TaskJuggler::ShiftAssignments
- TaskJuggler::ShiftAssignmentsAttribute
- TaskJuggler::ShiftScenario
- TaskJuggler::SimpleQueryExpander
- TaskJuggler::SortListAttribute
- TaskJuggler::StatusSheetReceiver
- TaskJuggler::StatusSheetReport
- TaskJuggler::StatusSheetSender
- TaskJuggler::StdIoWrapper
- TaskJuggler::StringAttribute
- TaskJuggler::SymbolAttribute
- TaskJuggler::SymbolListAttribute
- TaskJuggler::SyntaxReference
- TaskJuggler::TOCEntry
- TaskJuggler::TSResourceRecord
- TaskJuggler::TSTaskRecord
- TaskJuggler::TableColumnDefinition
- TaskJuggler::TableColumnSorter
- TaskJuggler::TableOfContents
- TaskJuggler::TableReport
- TaskJuggler::TableReportColumn
- TaskJuggler::TagFile
- TaskJuggler::TagFile::TagFileEntry
- TaskJuggler::Task
- TaskJuggler::TaskDepListAttribute
- TaskJuggler::TaskDependency
- TaskJuggler::TaskListAttribute
- TaskJuggler::TaskListRE
- TaskJuggler::TaskScenario
- TaskJuggler::TernarySearchTree
- TaskJuggler::TextFormatter
- TaskJuggler::TextParser
- TaskJuggler::TextParser::Macro
- TaskJuggler::TextParser::MacroTable
- TaskJuggler::TextParser::Pattern
- TaskJuggler::TextParser::Rule
- TaskJuggler::TextParser::Scanner
- TaskJuggler::TextParser::Scanner::BufferStreamHandle
- TaskJuggler::TextParser::Scanner::FileStreamHandle
- TaskJuggler::TextParser::Scanner::MacroStackEntry
- TaskJuggler::TextParser::Scanner::StreamHandle
- TaskJuggler::TextParser::SourceFileInfo
- TaskJuggler::TextParser::StackElement
- TaskJuggler::TextParser::State
- TaskJuggler::TextParser::StateTransition
- TaskJuggler::TextParser::TextParserResultArray
- TaskJuggler::TextParser::TokenDoc
- TaskJuggler::TextReport
- TaskJuggler::TimeInterval
- TaskJuggler::TimeIntervalListAttribute
- TaskJuggler::TimeSheet
- TaskJuggler::TimeSheetReceiver
- TaskJuggler::TimeSheetRecord
- TaskJuggler::TimeSheetReport
- TaskJuggler::TimeSheetSender
- TaskJuggler::TimeSheetSummary
- TaskJuggler::TimeSheets
- TaskJuggler::Tj3
- TaskJuggler::Tj3AppBase
- TaskJuggler::Tj3Client
- TaskJuggler::Tj3Daemon
- TaskJuggler::Tj3Man
- TaskJuggler::Tj3SheetAppBase
- TaskJuggler::Tj3SsReceiver
- TaskJuggler::Tj3SsSender
- TaskJuggler::Tj3TsReceiver
- TaskJuggler::Tj3TsSender
- TaskJuggler::Tj3TsSummary
- TaskJuggler::Tj3WebD
- TaskJuggler::TjException
- TaskJuggler::TjRuntimeError
- TaskJuggler::TjTime
- TaskJuggler::TjpExample
- TaskJuggler::TjpExportRE
- TaskJuggler::TjpSyntaxRules
- TaskJuggler::TraceReport
- TaskJuggler::URLParameter
- TaskJuggler::UserManual
- TaskJuggler::VimSyntax
- TaskJuggler::WebServer
- TaskJuggler::WelcomePage
- TaskJuggler::WorkingHours
- TaskJuggler::WorkingHoursAttribute
- TaskJuggler::XMLBlob
- TaskJuggler::XMLComment
- TaskJuggler::XMLDocument
- TaskJuggler::XMLElement
- TaskJuggler::XMLNamedText
- TaskJuggler::XMLText
- Diff
- Diff::Hunk
- AppConfig
- Diffable
- DiffableString
- Object
- RuntimeConfig
- String

No matching classes.

# TaskJuggler::Project

This class implements objects that hold all project properties. Project generally consist of resources, tasks and a number of other optional properties. Tasks, Resources, Accounts and Shifts are all build on the same underlying storage class PropertyTreeNode. Properties of the same kind are kept in PropertySet objects. There is only one PropertySet for each type of property. Additionally, each property may belong to various PropertyList objects. In contrast to PropertySet objects, PropertyList object have well defined sorting order and no information about the attributes of each type of property. The PropertySet holds the blueprints for the data construction inside the PropertyTreeNode objects. It contains the list of known Attributes.

### Attributes

accounts[R]
inputFiles[R]
outputDir[RW]
reportContexts[RW]
reports[R]
resources[R]
scenarios[R]
shifts[R]
tasks[R]
timeSheets[R]
warnTsDeltas[RW]

### Public Class Methods

maxScheduleGranularity() click to toggle source

TaskJuggler keeps all times in UTC. All time values must be multiples of the used scheduling granularity. If the local time zone is not hour-aligned to UTC, the maximum allowed schedule granularity is reduced.

    # File lib/taskjuggler/Project.rb, line 1003
    def Project.maxScheduleGranularity
      refTime = Time.gm(2000, 1, 1, 0, 0, 0)
      case (min = refTime.getlocal.min)
      when 0
        # We are hour-aligned to UTC; scheduleGranularity is 1 hour
        60 * 60
      when 30
        # We are half-hour off from UTC; scheduleGranularity is 30 minutes
        30 * 60
      when 15, 45
        # We are 15 or 45 minutes off from UTC; scheduleGranularity is 15
        # minutes
        15 * 60
      else
        raise "Unknown Time zone alignment #{min}"
      end
    end

new(id, name, version) click to toggle source

Create a project with the specified `id`, `name` and `version`. The constructor will set default values for all project attributes.

    # File lib/taskjuggler/Project.rb, line 63
    def initialize(id, name, version)
      AttributeBase.setMode(0)
      @attributes = {
        # This nested Array defines the supported alert levels. The lowest
        # level comes first at index 0 and the level rises from there on.
        # Currently, these levels are hardcoded. Each level entry has 3
        # members: the tjp syntax token, the user visible name and the
        # associated color as RGB byte array.
        'alertLevels' => AlertLevelDefinitions.new,
        'auxdir' => '',
        'copyright' => nil,
        'costaccount' => nil,
        'currency' => "EUR",
        'currencyFormat' => RealFormat.new([ '-', '', '', ',', 2 ]),
        'dailyworkinghours' => 8.0,
        'end' => nil,
        'flags' => [],
        'journal' => Journal.new,
        'limits' => nil,
        'leaves' => LeaveList.new,
        'loadUnit' => :days,
        'name' => name,
        'navigators' => {},
        'now' => TjTime.new.align(3600),
        'numberFormat' => RealFormat.new([ '-', '', '', '.', 1]),
        'priority' => 500,
        'projectid' => id || "prj",
        'projectids' => [ id ],
        'rate' => 0.0,
        'revenueaccount' => nil,
        'scheduleGranularity' => Project.maxScheduleGranularity,
        'shortTimeFormat' => "%H:%M",
        'start' => nil,
        'timeFormat' => "%Y-%m-%d",
        'timezone' => TjTime.timeZone,
        'trackingScenarioIdx' => nil,
        'version' => version || "1.0",
        'weekStartsMonday' => true,
        'workinghours' => nil,
        'yearlyworkingdays' => 260.714
      }

      # Before we can add any properties to this project, we need to define the
      # attributes that each of the property types will be using. In TaskJuggler
      # lingo, properties of a project are resources, tasks, accounts, shifts
      # and scenarios. Each of these properties can have lots of further
      # information attached to it. These bits of information are called
      # attributes. An attribute is defined by the AttributeDefinition class.
      # The PropertySet objects need to be fed with a list of such attribute
      # definitions to register the attributes with the properties.
      @scenarios = PropertySet.new(self, true)
      attrs = [
        # ID           Name          Type
        #     Inh.   Inh.Prj  Scen.  Default
        [ 'active',   'Enabled',    BooleanAttribute,
              true,  false,   false, true ],
        [ 'id',       'ID',         StringAttribute,
              false, false,   false, nil ],
        [ 'name',     'Name',       StringAttribute,
              false, false,   false, nil ],
        [ 'ownbookings', 'Own Bookings', BooleanAttribute,
              false, false,   false, true ],
        [ 'projection', 'Projection Mode', BooleanAttribute,
              true,  false,   false, false ],
        [ 'seqno',    'No',          FixnumAttribute,
              false, false,   false, nil ],
      ]
      attrs.each { |a| @scenarios.addAttributeType(AttributeDefinition.new(*a)) }

      @shifts = PropertySet.new(self, true)
      attrs = [
        # ID           Name            Type
        #     Inh.   Inh.Prj  Scen.  Default
        [ 'bsi',      'BSI',           StringAttribute,
              false, false,   false, "" ],
        [ 'id',       'ID',            StringAttribute,
              false, false,   false, nil ],
        [ 'index',     'Index',        FixnumAttribute,
              false, false,   false, -1 ],
        [ 'leaves',    'Leaves',       LeaveListAttribute,
              true,  true,    true,  LeaveList.new ],
        [ 'name',     'Name',          StringAttribute,
              false, false,   false, nil ],
        [ 'replace',   'Replace',      BooleanAttribute,
              true,  false,   true,  false ],
        [ 'seqno',    'No',            FixnumAttribute,
              false, false,   false, nil ],
        [ 'timezone',  'Time Zone',    StringAttribute,
              true,  true,    true,  TjTime.timeZone ],
        [ 'tree',      'Tree Index',   StringAttribute,
              false, false,   false, "" ],
        [ 'workinghours', 'Working Hours', WorkingHoursAttribute,
              true,  true,    true,  nil ]
      ]
      attrs.each { |a| @shifts.addAttributeType(AttributeDefinition.new(*a)) }

      @accounts = PropertySet.new(self, true)
      attrs = [
        # ID           Name            Type
        #     Inh.   Inh.Prj  Scen.  Default
        [ 'aggregate', 'Aggregate',    SymbolAttribute,
              true,  false,   false, :tasks ],
        [ 'bsi',       'BSI',          StringAttribute,
              false, false,   false, "" ],
        [ 'credits',   'Credits',      AccountCreditListAttribute,
              false, false,   true,  [] ],
        [ 'id',       'ID',         StringAttribute,
              false, false,   false, nil ],
        [ 'index',     'Index',        FixnumAttribute,
              false, false,   false, -1 ],
        [ 'flags',     'Flags',        FlagListAttribute,
              true,  false,   true,  [] ],
        [ 'name',     'Name',       StringAttribute,
              false, false,   false, nil ],
        [ 'seqno',    'No',          FixnumAttribute,
              false, false,   false, nil ],
        [ 'tree',      'Tree Index',   StringAttribute,
              false, false,   false, "" ]
      ]
      attrs.each { |a| @accounts.addAttributeType(AttributeDefinition.new(*a)) }

      @resources = PropertySet.new(self, true)
      attrs = [
        # ID           Name            Type
        #     Inh.   Inh.Prj  Scen.  Default
        [ 'alloctdeffort', 'Alloctd. Effort', FloatAttribute,
              false, false,   true,  0.0 ],
        [ 'bsi',       'BSI',          StringAttribute,
              false, false,   false, "" ],
        [ 'chargeset', 'Charge Sets',  ChargeSetListAttribute,
              true,  false,   true,  [] ],
        [ 'criticalness', 'Criticalness', FloatAttribute,
              false, false,   true,  0.0 ],
        [ 'duties',    'Duties',       TaskListAttribute,
              false, false,   true,  [] ],
        [ 'directreports', 'Direct Reports', ResourceListAttribute,
              false, false,   true,  [] ],
        [ 'efficiency','Efficiency',   FloatAttribute,
              true,  false,   true,  1.0 ],
        [ 'effort', 'Total Effort',    FixnumAttribute,
              false, false,   true,  0 ],
        [ 'email',     'Email',        StringAttribute,
              false, false,   false, nil ],
        [ 'fail',      'Failure Conditions', LogicalExpressionListAttribute,
              false, false,   false,  [] ],
        [ 'flags',     'Flags',        FlagListAttribute,
              true,  false,   true,  [] ],
        [ 'index',     'Index',        FixnumAttribute,
              false, false,   false, -1 ],
        [ 'leaveallowances', 'Leave Allowances', LeaveAllowanceListAttribute,
              true,  false,   true,  LeaveAllowanceList.new ],
        [ 'leaves',    'Leaves',       LeaveListAttribute,
              true,  true,    true,  LeaveList.new ],
        [ 'limits',    'Limits',       LimitsAttribute,
              true,  true,    true,  nil ],
        [ 'managers', 'Managers',      ResourceListAttribute,
              true,  false,   true,  [] ],
        [ 'rate',      'Rate',         FloatAttribute,
              true,  true,    true,  0.0 ],
        [ 'reports', 'Reports', ResourceListAttribute,
              false, false,   true,  [] ],
        [ 'seqno',    'No',          FixnumAttribute,
              false, false,   false, nil ],
        [ 'shifts',    'Shifts',       ShiftAssignmentsAttribute,
              true, false,    true,  nil ],
        [ 'tree',      'Tree Index',   StringAttribute,
              false, false,   false, "" ],
        [ 'warn',      'Warning Condition', LogicalExpressionListAttribute,
              false, false,   false, [] ],
        [ 'workinghours', 'Working Hours', WorkingHoursAttribute,
              true,  true,    true,  nil ]
      ]
      attrs.each { |a| @resources.addAttributeType(AttributeDefinition.new(*a)) }

      @tasks = PropertySet.new(self, false)
      attrs = [
        # ID           Name            Type
        #     Inh.   Inh.Prj  Scen.  Default
        [ 'allocate', 'Allocations',   AllocationAttribute,
              true,  false,   true,  [] ],
        [ 'assignedresources', 'Assigned Resources', ResourceListAttribute,
              false, false,   true,  [] ],
        [ 'booking',   'Bookings',     BookingListAttribute,
              false, false,   true,  [] ],
        [ 'bsi',       'BSI',          StringAttribute,
              false, false,   false, "" ],
        [ 'charge',    'Charges',      ChargeListAttribute,
              false, false,   true,  [] ],
        [ 'chargeset', 'Charge Sets',  ChargeSetListAttribute,
              true,  false,   true,  [] ],
        [ 'complete',  'Completion',   FloatAttribute,
              false, false,   true,  nil ],
        [ 'competitors', 'Competitors', TaskListAttribute,
              false, false,   true,  [] ],
        [ 'criticalness', 'Criticalness', FloatAttribute,
              false, false,   true,  0.0 ],
        [ 'depends',   'Preceding tasks', DependencyListAttribute,
              true,  false,   true,  [] ],
        [ 'duration',  'Duration',     DurationAttribute,
              false, false,   true,  0 ],
        [ 'effort',    'Effort',       DurationAttribute,
              false, false,   true,  0 ],
        [ 'end',       'End',          DateAttribute,
              false, false,   true,  nil ],
        [ 'endpreds',  'End Preds.',   TaskDepListAttribute,
              false, false,   true,  [] ],
        [ 'endsuccs',  'End Succs.',   TaskDepListAttribute,
              false, false,   true,  [] ],
        [ 'fail',      'Failure Conditions', LogicalExpressionListAttribute,
              false, false,   false, [] ],
        [ 'flags',     'Flags',        FlagListAttribute,
              true,  false,   true,  [] ],
        [ 'forward',   'Scheduling',   BooleanAttribute,
              true,  false,   true,  true ],
        [ 'gauge',     'Schedule gauge', StringAttribute,
              false, false,   true,  nil ],
        [ 'id',       'ID',         StringAttribute,
              false, false,   false, nil ],
        [ 'index',     'Index',        FixnumAttribute,
              false, false,   false, -1 ],
        [ 'length',    'Length',       DurationAttribute,
              false, false,   true,  0 ],
        [ 'limits',    'Limits',       LimitsAttribute,
              false, false,   true,  nil ],
        [ 'maxend',    'Max. End',     DateAttribute,
              true,  false,   true,  nil ],
        [ 'maxstart',  'Max. Start',   DateAttribute,
              false, false,   true,  nil ],
        [ 'milestone', 'Milestone',    BooleanAttribute,
              false, false,   true,  false ],
        [ 'minend',    'Min. End',     DateAttribute,
              false, false,   true,  nil ],
        [ 'minstart',  'Min. Start',   DateAttribute,
              true,  false,   true,  nil ],
        [ 'name',     'Name',       StringAttribute,
              false, false,   false, nil ],
        [ 'note',      'Note',         RichTextAttribute,
              false, false,   false, nil ],
        [ 'pathcriticalness', 'Path Criticalness', FloatAttribute,
              false, false,   true, 0.0 ],
        [ 'precedes',  'Following tasks', DependencyListAttribute,
              true,  false,   true,  [] ],
        [ 'priority',  'Priority',     FixnumAttribute,
              true,  true,    true,  500 ],
        [ 'projectid', 'Project ID',   SymbolAttribute,
              true,  true,    true,  nil ],
        [ 'responsible', 'Responsible', ResourceListAttribute,
              true,  false,   true,  [] ],
        [ 'scheduled', 'Scheduled',    BooleanAttribute,
              true,  false,   true,  false ],
        [ 'seqno',    'No',          FixnumAttribute,
              false, false,   false, nil ],
        [ 'shifts',     'Shifts',      ShiftAssignmentsAttribute,
              true,  false,   true, nil ],
        [ 'start',     'Start',        DateAttribute,
              false, false,   true,  nil ],
        [ 'startpreds', 'Start Preds.', TaskDepListAttribute,
              false, false,   true,  [] ],
        [ 'startsuccs', 'Start Succs.', TaskDepListAttribute,
              false, false,   true,  [] ],
        [ 'status',    'Task Status',  StringAttribute,
              false, false,   true,  "" ],
        [ 'tree',      'Tree Index',   StringAttribute,
              false, false,   false, "" ],
        [ 'warn',      'Warning Condition', LogicalExpressionListAttribute,
              false, false,   false, [] ]
      ]
      attrs.each { |a| @tasks.addAttributeType(AttributeDefinition.new(*a)) }

      @reports = PropertySet.new(self, false)
      attrs = [
        # ID           Name            Type
        #     Inh.   Inh.Prj  Scen.  Default
        [ 'accountroot',  'Account Root',    PropertyAttribute,
              true,  false,   false, nil ],
        [ 'auxdir', 'Auxiliary files directory', StringAttribute,
              true,  true,    false, '' ],
        [ 'bsi',       'BSI',          StringAttribute,
              false, false,   false, '' ],
        [ 'caption',   'Caption',      RichTextAttribute,
              true,  false,   false, nil ],
        [ 'center',    'Center',       RichTextAttribute,
              true,  false,   false, nil ],
        [ 'columns',   'Columns',      ColumnListAttribute,
              true,  false,   false, [] ],
        [ 'costaccount', 'Cost Account', AccountAttribute,
              true,  true,    false, nil ],
        [ 'currencyFormat', 'Currency Format', RealFormatAttribute,
              true,  true,    false, nil ],
        [ 'definitions', 'Definitions', DefinitionListAttribute,
              true,  false,   false, KeywordArray.new([ '*' ]) ],
        [ 'end',       'End',          DateAttribute,
              true,  true,    false, nil ],
        [ 'epilog',    'Epilog',       RichTextAttribute,
              true,  false,   false, nil ],
        [ 'flags',     'Flags',        FlagListAttribute,
              true,  false,   true,  [] ],
        [ 'footer',    'Footer',       RichTextAttribute,
              true,  false,   false, nil ],
        [ 'formats',   'Formats',      FormatListAttribute,
              true,  false,   false, [] ],
        [ 'ganttBars', 'Gantt Bars',   BooleanAttribute,
              true,  false,   false, true ],
        [ 'header',    'Header',       RichTextAttribute,
              true,  false,   false, nil ],
        [ 'headline',  'Headline',     RichTextAttribute,
              true,  false,   false, nil ],
        [ 'hideAccount', 'Hide Account', LogicalExpressionAttribute,
              true,  false,   false, nil ],
        [ 'hideJournalEntry', 'Hide JournalEntry', LogicalExpressionAttribute,
              true,  false,   false, nil ],
        [ 'hideResource', 'Hide Resource', LogicalExpressionAttribute,
              true,  false,   false, nil ],
        [ 'hideTask',  'Hide Task',    LogicalExpressionAttribute,
              true,  false,   false, nil ],
        [ 'height',    'Height',       FixnumAttribute,
              false,  false,   false, 480 ],
        [ 'id',       'ID',         StringAttribute,
              false, false,   false, nil ],
        [ 'index',     'Index',        FixnumAttribute,
              false, false,   false, -1 ],
        [ 'interactive', 'Interactive', BooleanAttribute,
              false, false,   false, false ],
        [ 'journalAttributes', 'Journal Attributes', SymbolListAttribute,
              true,  false,   false, KeywordArray.new([ '*' ]) ],
        [ 'journalMode', 'Journal Mode', SymbolAttribute,
              true,  false,   false, :journal ],
        [ 'left',      'Left',         RichTextAttribute,
              true,  false,   false, nil ],
        [ 'loadUnit',  'Load Unit',    StringAttribute,
              true,  true,    false, nil ],
        [ 'name',     'Name',       StringAttribute,
              false, false,   false, nil ],
        [ 'now',       'Now',          DateAttribute,
              true,  true,    false, nil ],
        [ 'numberFormat', 'Number Format', RealFormatAttribute,
              true,  true,    false, nil ],
        [ 'openNodes', 'Open Nodes',   NodeListAttribute,
              false, false,   false, nil ],
        [ 'prolog',    'Prolog',       RichTextAttribute,
              true, false,   false, nil ],
        [ 'rawHtmlHead', 'Raw HTML Header', StringAttribute,
              true, false,   false, nil ],
        [ 'resourceAttributes', 'Resource Attributes', FormatListAttribute,
              true,  false,   false, KeywordArray.new([ '*' ]) ],
        [ 'resourceroot',  'resource Root', PropertyAttribute,
              true,  false,   false, nil ],
        [ 'revenueaccount', 'Revenue Account', AccountAttribute,
              true,  true,    false, nil ],
        [ 'right',     'Right',        RichTextAttribute,
              true,  false,   false, nil ],
        [ 'rollupAccount', 'Rollup Account', LogicalExpressionAttribute,
              true,  false,   false, nil ],
        [ 'rollupResource', 'Rollup Resource', LogicalExpressionAttribute,
              true,  false,   false, nil ],
        [ 'rollupTask', 'Rollup Task', LogicalExpressionAttribute,
              true, false,    false, nil ],
        [ 'scenarios',  'Scenarios',   ScenarioListAttribute,
              true, false,    false, [ 0 ] ],
        [ 'selfcontained', 'Selfcontained', BooleanAttribute,
              true, false,    false, false ],
        [ 'seqno',    'No',          FixnumAttribute,
              false, false,   false, nil ],
        [ 'shortTimeFormat', 'Short Time Format', StringAttribute,
              true,  true,    false, nil ],
        [ 'sortAccounts', 'Sort Accounts', SortListAttribute,
              true,  false,   false, [[ 'seqno', true, -1 ]] ],
        [ 'sortJournalEntries', 'Sort Journal Entries', JournalSortListAttribute,
              true,  false,   false, [[ :alert, 1 ], [ :date, 1 ], [ :seqno, 1 ]] ],
        [ 'sortResources', 'Sort Resources', SortListAttribute,
              true,  false,   false, [[ 'seqno', true, -1 ]] ],
        [ 'sortTasks', 'Sort Tasks',   SortListAttribute,
              true,  false,   false, [[ 'seqno', true, -1 ]] ],
        [ 'start',     'Start',        DateAttribute,
              true,  true,    false, nil ],
        [ 'taskAttributes', 'Task Attributes', FormatListAttribute,
              true,  false,   false, KeywordArray.new([ '*' ]) ],
        [ 'taskroot',  'Task Root',    PropertyAttribute,
              true,  false,   false, nil ],
        [ 'timeFormat', 'Time Format', StringAttribute,
              true,  true,    false, nil ],
        [ 'timeOffId',  'Time Off ID', StringAttribute,
              false,  false,  false, nil ],
        [ 'timeOffName',  'Time Off Name', StringAttribute,
              false,  false,  false, nil ],
        [ 'timezone', 'Time Zone',     StringAttribute,
              true,  true,    false, TjTime.timeZone ],
        [ 'title',    'Title',         StringAttribute,
              true,  false,   false, nil ],
        [ 'tree',      'Tree Index',   StringAttribute,
              false, false,   false, "" ],
        [ 'weekStartsMonday', 'Week Starts Monday', BooleanAttribute,
              true,  true,    false, false ],
        [ 'width',     'Width',        FixnumAttribute,
              true,  false,   false, 640 ]
      ]
      attrs.each { |a| @reports.addAttributeType(AttributeDefinition.new(*a)) }

      Scenario.new(self, 'plan', 'Plan Scenario', nil)

      # A list of files that contained the project data.
      @inputFiles = FileList.new

      @timeSheets = TimeSheets.new

      # A scoreboard that reflects the global working hours and leaves.
      @scoreboard = nil
      # A scoreboard that reflects the global working hours but no leaves.
      @scoreboardNoLeaves = nil

      # The ReportContext provides additional settings to the report that can
      # complement or replace the report attributes. Reports can include other
      # reports. During report generation, only one context is active, but the
      # context of enclosing reports needs to be preserved. Therefor we use a
      # stack to implement this.
      @reportContexts = []
      @outputDir = './'
      @warnTsDeltas = false
    end

### Public Instance Methods

[](name) click to toggle source

Query the value of a Project attribute. name is the ID of the attribute.

    # File lib/taskjuggler/Project.rb, line 490
    def [](name)
      if !@attributes.has_key?(name)
        raise "Unknown project attribute #{name}"
      end
      @attributes[name]
    end

[]=(name, value) click to toggle source

Set the Project attribute with ID name to value.

    # File lib/taskjuggler/Project.rb, line 498
    def []=(name, value)
      if !@attributes.has_key?(name)
        raise "Unknown project attribute #{name}"
      end
      @attributes[name] = value

      # If the start, end or schedule granularity have been changed, we have
      # to reset the working hours.
      if %(start end scheduleGranularity timezone timingresolution).
        include?(name)
        if @attributes['start'] && @attributes['end']
          @attributes['workinghours'] =
            WorkingHours.new(@attributes['scheduleGranularity'],
                             @attributes['start'], @attributes['end'],
                             @attributes['timezone'])
        end
      end
      value
    end

account(id) click to toggle source

Return the Account with the ID id or return nil if it does not exist.

    # File lib/taskjuggler/Project.rb, line 586
    def account(id)
      @accounts[id]
    end

anyResourceAvailable?(sbIdx) click to toggle source

Return true if for the date specified by the global scoreboard index sbIdx there is any resource that is available.

    # File lib/taskjuggler/Project.rb, line 995
    def anyResourceAvailable?(sbIdx)
      @resourceAvailability[sbIdx]
    end

attributeName(id) click to toggle source

Return the name of the attribute id. Since we don't know whether we are looking for a task, resource, etc. attribute, we prefer tasks over resources here.

    # File lib/taskjuggler/Project.rb, line 1024
    def attributeName(id)
      # We have to see if the attribute id is a task or resource attribute and
      # return it's name.
      (name = @tasks.attributeName(id)).nil? &&
      (name = @resources.attributeName(id)).nil?
      name
    end

checkReports() click to toggle source

Make sure that we have a least one report defined that has an output format.

    # File lib/taskjuggler/Project.rb, line 684
    def checkReports
      if @reports.empty?
        warning('no_report_defined',
                "This project has no reports defined. " +
                "No output data will be generated.")
      end

      unless @accounts.empty?
        @reports.each do |report|
          if (report.typeSpec != :accountreport) &&
             (report.get('costaccount').nil? ||
              report.get('revenueaccount').nil?)
            warning('report_without_balance',
                    "The report #{report.fullId} has no 'balance' defined. " +
                    "No cost or revenue computation will be possible.",
                    report.sourceFileInfo)
          end
        end
      end

      @reports.each do |report|
        return unless report.get('formats').empty?
      end

      warning('all_formats_empty',
              "None of the reports has a 'formats' attribute. " +
              "No output data will be generated.")
    end

checkTimeSheets() click to toggle source

    # File lib/taskjuggler/Project.rb, line 816
    def checkTimeSheets
      @timeSheets.check
    end

collectTimeOffIntervals(iv, minDuration) click to toggle source

    # File lib/taskjuggler/Project.rb, line 962
    def collectTimeOffIntervals(iv, minDuration)
      @scoreboard.collectIntervals(iv, minDuration) do |val|
        val.is_a?(Fixnum) && (val & 0x3E) != 0
      end
    end

convertToDailyLoad(seconds) click to toggle source

Convert working seconds to working days. The result depends on the setting of the global 'dailyworkinghours' attribute.

    # File lib/taskjuggler/Project.rb, line 921
    def convertToDailyLoad(seconds)
      seconds / (@attributes['dailyworkinghours'] * 3600.0)
    end

dailyWorkingHours() click to toggle source

Return the average number of working hours per day. This defaults to 8 but can be set to other values by the user.

    # File lib/taskjuggler/Project.rb, line 525
    def dailyWorkingHours
      @attributes['dailyworkinghours'].to_f
    end

dateToIdx(date, forceIntoProject = true) click to toggle source

Convert a date (TjTime) to the equivalent Scoreboard index. If forceIntoProject is true, the date will be pushed into the project time frame.

    # File lib/taskjuggler/Project.rb, line 947
    def dateToIdx(date, forceIntoProject = true)
      if (date < @attributes['start'] || date > @attributes['end'])
        # Date is out of range.
        if forceIntoProject
          return 0 if date < @attributes['start']
          return scoreboardSize - 1 if date > @attributes['end']
        else
          raise "Date #{date} is out of project time range " +
                "(#{@attributes['start']} - #{@attributes['end']})"
        end
      end
      # Calculate the corresponding index.
      ((date - @attributes['start']) / @attributes['scheduleGranularity']).to_i
    end

deep_clone() click to toggle source

Overload the deep_clone function so that references to the project don't lead to deep copying of the whole project.

    # File lib/taskjuggler/Project.rb, line 485
    def deep_clone
      self
    end

enableTraceReports(enable) click to toggle source

Add the CSV output format to all reports of type 'tracereport' if enable is true. Otherwise remove all CSV output formats.

    # File lib/taskjuggler/Project.rb, line 666
    def enableTraceReports(enable)
      @reports.each do |report|
         next unless report.typeSpec == :tracereport

         if enable
           # Enable the CSV format for the tracereport
           unless report.get('formats').include?(:csv)
             report.get('formats') << :csv
           end
         else
           # Disabe CSV format for the tracereport
           report.get('formats').delete(:csv)
         end
      end
    end

generateReport(reportId, regExpMode, formats = nil, dynamicAttributes = nil) click to toggle source

    # File lib/taskjuggler/Project.rb, line 763
    def generateReport(reportId, regExpMode, formats = nil,
                       dynamicAttributes = nil)
      reportList = regExpMode ? reportList = matchingReports(reportId) :
                                [ reportId ]
      reportList.each do |id|
        unless (report = @reports[id])
          error('unknown_report_id',
                "Request to generate unknown report #{id}")
        end
        if formats.nil? && report.get('formats').empty?
          error('formats_empty',
                "The report #{report.fullId} has no 'formats' attribute. " +
                "No output data will be generated.", report.sourceFileInfo)
        end

        Log.startProgressMeter("Report #{report.name}")
        @reportContexts.push(context = ReportContext.new(self, report))

        # If we have dynamic attributes we need to backup the old attributes
        # first, then parse the dynamicAttributes String replacing the
        # original values.
        if dynamicAttributes
          unless dynamicAttributes.empty?
            context.attributeBackup = report.backupAttributes
            parser = ProjectFileParser.new
            parser.parseReportAttributes(report, dynamicAttributes)
          end
          report.set('interactive', true)
        end

        report.generate(formats)

        if dynamicAttributes && !dynamicAttributes.empty?
          report.restoreAttributes(context.attributeBackup)
        end
        @reportContexts.pop
        Log.stopProgressMeter
      end
    end

generateReports(maxCpuCores) click to toggle source

Call this function to generate the reports based on the scheduling result. This function may only be called after Project#schedule has been called.

    # File lib/taskjuggler/Project.rb, line 715
    def generateReports(maxCpuCores)
      @reports.index
      if maxCpuCores == 1
        @reports.each do |report|
          # Skip reports that don't have any format specified or trace reports
          # when generateTraces is false.
          next if report.get('formats').empty?

          Log.startProgressMeter("Report #{report.name}")
          @reportContexts.push(ReportContext.new(self, report))
          report.generate
          @reportContexts.pop
          Log.stopProgressMeter
        end
      else
        # Kickoff the generation of all reports by pushing the jobs into the
        # BatchProcessor queue.
        bp = BatchProcessor.new(maxCpuCores)
        @reports.each do |report|
          # Skip reports that don't have any format specified or trace reports
          # when generateTraces is false.
          next if report.get('formats').empty? ||
                  (report.typeSpec == :trace && !generateTraces)

          bp.queue(report) {
            @reportContexts.push(ReportContext.new(self, report))
            res = report.generate
            @reportContexts.pop
            res
          }
        end
        # Now wait for all the jobs to finish.
        bp.wait do |report|
          Log.startProgressMeter("Report #{report.tag.name}")
          $stdout.print(report.stdout)
          $stderr.print(report.stderr)
          if report.retVal.signaled?
            error('rg_signal', "Signal raised")
          end
          unless report.retVal.success?
            error('rg_abort', "Process aborted")
          end
          Log.stopProgressMeter
        end
      end
      DataCache.instance.flush
    end

getWorkSlots(startIdx, endIdx) click to toggle source

Return the number of global working slots during the given time interval specified by startIdx and endIdx. This method takes global leaves into account.

    # File lib/taskjuggler/Project.rb, line 983
    def getWorkSlots(startIdx, endIdx)
      slots = 0
      startIdx.upto(endIdx) do |idx|
        slots += 1 unless @scoreboard[idx]
      end

      slots
    end

hasWorkingTime(startTime, endTime) → true or false click to toggle source
hasWorkingTime(interval) → true or false

Return true if the interval overlaps with a globally defined working time or false if not. Global work time means, no global leaves defined and the slot lies within a defined global working time period.

    # File lib/taskjuggler/Project.rb, line 898
    def hasWorkingTime(*args)
      # Normalize argument(s) to TimeInterval
      if args.length == 1
        if args[0].is_a?(TimeInterval)
          startIdx = dateToIdx(args[0].start)
          endIdx = dateToIdx(args[0].end)
        else
          raise ArgumentError, "Unsupported argument type #{args[0].class}"
        end
      else
        startIdx = dateToIdx(args[0])
        endIdx = dateToIdx(args[1])
      end

      startIdx.upto(endIdx) do |idx|
        return true if @scoreboard[idx]
      end

      false
    end

idxToDate(idx) click to toggle source

Convert a Scoreboard index to the equivalent date. idx is the index and it must be within the range of the Scoreboard objects. If not, an exception is raised.

    # File lib/taskjuggler/Project.rb, line 937
    def idxToDate(idx)
      if $DEBUG && (idx < 0 || idx > scoreboardSize)
        raise "Scoreboard index out of range"
      end
      @attributes['start'] + idx * @attributes['scheduleGranularity']
    end

isWorkingTime(slotIdx) → true or false click to toggle source
isWorkingTime(slot) → true or false
isWorkingTime(startTime, endTime) → true or false
isWorkingTime(interval) → true or false

Return true if the slot or interval is withing globally defined working time or false if not. If the argument is a TimeInterval, all slots of the interval must be working time to return true as result. Global work time means, no global leaves defined and the slot lies within a defined global working time period.

    # File lib/taskjuggler/Project.rb, line 866
    def isWorkingTime(*args)
      # Normalize argument(s) to TimeInterval
      if args.length == 1
        if args[0].is_a?(Fixnum) || args[0].is_a?(Bignum)
          return @scoreboard[args[0]].nil?
        elsif args[0].is_a?(TjTime)
          return @scoreboard[dateToIdx(args[0])].nil?
        elsif args[0].is_a?(TimeInterval)
          startIdx = dateToIdx(args[0].start)
          endIdx = dateToIdx(args[0].end)
        else
          raise ArgumentError, "Unsupported argument type #{args[0].class}"
        end
      else
        startIdx = dateToIdx(args[0])
        endIdx = dateToIdx(args[1])
      end

      startIdx.upto(endIdx) do |idx|
        return false if @scoreboard[idx]
      end

      true
    end

journal(query) click to toggle source

    # File lib/taskjuggler/Project.rb, line 1032
    def journal(query)
      @attributes['journal'].to_rti(query)
    end

listReports(reportId, regExpMode) click to toggle source

    # File lib/taskjuggler/Project.rb, line 803
    def listReports(reportId, regExpMode)
      reportList = regExpMode ? reportList = matchingReports(reportId) :
                                @reports[reportId] ? [ reportId ] : []
      puts "No match for #{reportId}" if reportList.empty?
      reportList.each do |id|
        report = @reports[id]
        formats = report.get('formats')
        next if formats.empty?

        puts sprintf("%s\t%s\t%s", id, formats.join(', '), report.name)
      end
    end

monthlyWorkingDays() click to toggle source

Return the average number of working days per month.

    # File lib/taskjuggler/Project.rb, line 535
    def monthlyWorkingDays
      @attributes['yearlyworkingdays'] / 12.0
    end

report(id) click to toggle source

Return the Report with the ID `id` or return nil if it does not exist.

    # File lib/taskjuggler/Project.rb, line 601
    def report(id)
      @reports[id]
    end

reportByName(name) click to toggle source

Return the Report with the name `name` or return nil if it does not exist.

    # File lib/taskjuggler/Project.rb, line 607
    def reportByName(name)
      @reports.each do |report|
        return report if report.name == name
      end
      nil
    end

resource(id) click to toggle source

Return the Resource with the ID id or return nil if it does not exist.

    # File lib/taskjuggler/Project.rb, line 596
    def resource(id)
      @resources[id]
    end

scenario(index) → Scenario click to toggle source
scenario(id) → Scenario

Return the Scenario with the given id or index.

    # File lib/taskjuggler/Project.rb, line 554
    def scenario(arg)
      if arg.is_a?(Fixnum)
        @scenarios.each do |sc|
          return sc if sc.sequenceNo - 1 == arg
        end
      else
        return @scenarios[arg]
      end
      nil
    end

scenarioCount() click to toggle source

Return the number of defined scenarios for the project.

    # File lib/taskjuggler/Project.rb, line 519
    def scenarioCount
      @scenarios.items
    end

scenarioIdx(scenario) click to toggle source
scenarioIdx(id)

Return the index of the given Scenario specified by scenario or id.

    # File lib/taskjuggler/Project.rb, line 570
    def scenarioIdx(sc)
      if sc.is_a?(Scenario)
        return sc.sequenceNo - 1
      elsif @scenarios[sc].nil?
        return nil
      else
        return @scenarios[sc].sequenceNo - 1
      end
    end

schedule() click to toggle source

This function must be called after the Project data structures have been filled with data. It schedules all scenario and stores the result in the data structures again.

    # File lib/taskjuggler/Project.rb, line 617
    def schedule
      initScoreboards

      [ @accounts, @shifts, @resources, @tasks ].each do |p|
        # Set all index counters to their proper values.
        p.index
      end

      if @tasks.empty?
        error('no_tasks', "No tasks defined")
      end

      @scenarios.each do |sc|
        # Skip disabled scenarios
        next unless sc.get('active')

        scIdx = scenarioIdx(sc)

        # All user provided values are set now. The next step is to
        # propagate inherited values. These values must be marked as
        # inherited by setting the mode to 1. As we always call
        # PropertyTreeNode#inherit this is just a safeguard.
        AttributeBase.setMode(1)
        prepareScenario(scIdx)

        # Now change to mode 2 so all values that are modified are marked
        # as computed.
        AttributeBase.setMode(2)
        # Schedule the scenario.
        scheduleScenario(scIdx)

        # Complete the data sets, and check the result.
        finishScenario(scIdx)
      end

      resources.each do |resource|
        resource.checkFailsAndWarnings
      end

      tasks.each do |task|
        task.checkFailsAndWarnings
      end

      @timeSheets.warnOnDelta if @warnTsDeltas
      true
    end

scoreboardSize() click to toggle source

Many internal data structures use Scoreboard objects to keep track of scheduling data. These have one entry for every schedulable time slot in the project time frame. This functions returns the number of entries in the scoreboards.

    # File lib/taskjuggler/Project.rb, line 929
    def scoreboardSize
      ((@attributes['end'] - @attributes['start']) /
       @attributes['scheduleGranularity']).to_i
    end

shift(id) click to toggle source

Return the Shift with the ID id or return nil if it does not exist.

    # File lib/taskjuggler/Project.rb, line 581
    def shift(id)
      @shifts[id]
    end

slotsToDays(slots) click to toggle source

Convert timeSlots to working days.

    # File lib/taskjuggler/Project.rb, line 545
    def slotsToDays(slots)
      slots * @attributes['scheduleGranularity'] / (60 * 60 * dailyWorkingHours)
    end

task(id) click to toggle source

Return the Task with the ID id or return nil if it does not exist.

    # File lib/taskjuggler/Project.rb, line 591
    def task(id)
      @tasks[id]
    end

to_s() click to toggle source

Print the attribute values. It's used for debugging only.

    # File lib/taskjuggler/Project.rb, line 1037
    def to_s
      #raise "STOP!"
      str = ''
      @attributes.each do |attribute, value|
        if value
          str += "#{attribute}: " +
                 "#{value.is_a?(PropertyTreeNode) ? value.fullId : value}"
        end
      end
      str
    end

weeklyWorkingDays() click to toggle source

    # File lib/taskjuggler/Project.rb, line 529
    def weeklyWorkingDays
      @attributes['workinghours'].weeklyWorkingHours /
        @attributes['dailyworkinghours']
    end

workingDays(interval) click to toggle source

Return the number of working days (ignoring global leaves) during the given interval.

    # File lib/taskjuggler/Project.rb, line 970
    def workingDays(interval)
      startIdx = dateToIdx(interval.start)
      endIdx = dateToIdx(interval.end)
      slots = 0
      startIdx.upto(endIdx) do |idx|
        slots += 1 unless @scoreboardNoLeaves[idx]
      end
      slotsToDays(slots)
    end

yearlyWorkingDays() click to toggle source

Return the average number of working days per year.

    # File lib/taskjuggler/Project.rb, line 540
    def yearlyWorkingDays
      @attributes['yearlyworkingdays'].to_f
    end

### Protected Instance Methods

finishScenario(scIdx) click to toggle source

    # File lib/taskjuggler/Project.rb, line 1128
    def finishScenario(scIdx)
      Log.enter('finishScenario',
                "Finishing scenario #{scenario(scIdx).get('name')}")
      Log.startProgressMeter("Checking scenario #{scenario(scIdx).get('name')}")
      @tasks.each do |task|
        # Recursively traverse the top-level tasks to finish all tasks.
        task.finishScheduling(scIdx) unless task.parent
      end

      @resources.each do |resource|
        # Recursively traverse the top-level resources to finish them all.
        resource.finishScheduling(scIdx) unless resource.parent
      end

      i = 0
      total = @tasks.items
      @tasks.each do |task|
        task.postScheduleCheck(scIdx) if task.parent.nil?
        i += 1
        Log.progress(i.to_f / total)
      end

      Log.stopProgressMeter
      Log.exit('finishScenario',
               "Finishing scenario #{scenario(scIdx).get('name')} completed")
    end

prepareScenario(scIdx) click to toggle source

    # File lib/taskjuggler/Project.rb, line 1051
    def prepareScenario(scIdx)
      Log.enter('prepareScenario',
                "Finishing scenario #{scenario(scIdx).get('name')}")
      Log.startProgressMeter("Preparing scenario " +
                             "#{scenario(scIdx).get('name')}")
      resources = PropertyList.new(@resources)
      tasks = PropertyList.new(@tasks)

      # Compile a list of leaf resources that are actually used in this
      # project.
      usedResources = []
      tasks.each do |task|
        task.candidates(scIdx).each do |resource|
          usedResources << resource unless usedResources.include?(resource)
        end
      end
      total = usedResources.length
      i = 0
      usedResources.each do |resource|
        resource.prepareScheduling(scIdx)
        resource.preScheduleCheck(scIdx)
        i += 1
        Log.progress((i.to_f / total) * 0.8)
      end

      resources.each { |resource| resource.setDirectReports(scIdx) }
      resources.each { |resource| resource.setReports(scIdx) }

      computeResourceAvailabilities(scIdx, usedResources)

      Log.progress(0.81)
      tasks.each { |task| task.prepareScheduling(scIdx) }
      Log.progress(0.82)
      tasks.each { |task| task.Xref(scIdx) }
      tasks.each { |task| task.propagateInitialValues(scIdx) }
      Log.progress(0.83)
      tasks.each { |task| task.preScheduleCheck(scIdx) }

      Log.progress(0.84)
      # Check for dependency loops in the task graph.
      tasks.each { |task| task.resetLoopFlags(scIdx) }
      tasks.each do |task|
        task.checkForLoops(scIdx, [], false, true, true) if task.parent.nil?
      end
      Log.progress(0.85)
      tasks.each { |task| task.resetLoopFlags(scIdx) }
      tasks.each do |task|
        task.checkForLoops(scIdx, [], true, true, false) if task.parent.nil?
      end
      Log.progress(0.87)

      # Compute the criticalness of the tasks and their pathes.
      tasks.each { |task| task.countResourceAllocations(scIdx) }
      Log.progress(0.88)
      resources.each { |resource| resource.calcCriticalness(scIdx) }
      Log.progress(0.9)
      tasks.each { |task| task.calcCriticalness(scIdx) }
      Log.progress(0.95)
      tasks.each { |task| task.calcPathCriticalness(scIdx) }
      Log.progress(0.99)
      @timeSheets.check
      Log.progress(1.0)

      Log.stopProgressMeter
      # This is used for debugging only
      if false
        resources.each do |resource|
          puts "#{resource}"
        end
        tasks.each do |task|
          puts "#{task}"
        end
      end
      Log.exit('prepareScenario',
               "Preparing scenario #{scenario(scIdx).get('name')} completed")
    end

scheduleScenario(scIdx) click to toggle source

Schedule all tasks for the given Scenario with index `scIdx`.

    # File lib/taskjuggler/Project.rb, line 1156
    def scheduleScenario(scIdx)
      tasks = PropertyList.new(@tasks)
      # Only care about leaf tasks that are not milestones and aren't
      # scheduled already (marked with the 'scheduled' attribute).
      tasks.delete_if { |task| !task.leaf? ||
                               task['milestone', scIdx] ||
                               task['scheduled', scIdx] }

      Log.enter('scheduleScenario', "#{tasks.length} leaf tasks")
      # The sorting of the work item list determines which tasks will get their
      # resources first. The first sorting criterium is the user specified task
      # priority. The second criterium is the scheduler determined priority
      # stored in the pathcriticalness attribute. That way, the user can always
      # override the scheduler determined priority. To always have a defined
      # order, the third criterium is the sequence number.
      tasks.setSorting([ [ 'priority', false, scIdx ],
                         [ 'pathcriticalness', false, scIdx ],
                         [ 'seqno', true, -1 ] ])
      tasks.sort!
      totalTasks = tasks.length

      # Enter the main scheduling loop. This loop is only terminated when all
      # tasks have been scheduled or another thread has set the breakFlag to
      # true.
      Log.startProgressMeter("Scheduling scenario " +
                             "#{scenario(scIdx).get('name')}")
      failedTasks = []
      while !tasks.empty?
        # Only update the progress bar every 10 completed tasks.
        if tasks.length % 10 == 0
          percentComplete = (totalTasks - tasks.length).to_f / totalTasks
          Log.progress(percentComplete)
        end

        # Now find the task with the highest priority that can be scheduled
        # and schedule it.
        taskToRemove = nil
        tasks.each do |task|
          # Task not ready? Ignore it.
          next unless task.readyForScheduling?(scIdx)

          unless task.schedule(scIdx)
            failedTasks << task
          end
          # The task has been completed or failed. But we can remove it from
          # the todo list.
          taskToRemove = task
          # The scheduling of this task may cause other higher priority tasks
          # to be ready now. So we terminate the inner loop and start at the
          # top of the list again.
          break
        end

        # There should always be a task to be removed. If not, the scheduler
        # has found a set of tasks that deadlock each other.
        if taskToRemove
          tasks.delete(taskToRemove)
        elsif failedTasks.empty?
          warning('deadlock',
                  'Some tasks reference each other but don\t provide ' +
                  'enough information to start the scheduling. The ' +
                  'scheduler does not know where to start scheduling ' +
                  'these tasks. You need to provide more fixed dates ' +
                  'or dependencies on already scheduled tasks.')
          failedTasks = tasks
          break
        else
          # We have some tasks that cannot be scheduled.
          break
        end
      end

      # Check for failed tasks and report the first 10 of them as
      # warnings.
      unless failedTasks.empty?
        warning('unscheduled_tasks',
                "#{failedTasks.length} tasks could not be scheduled")
        i = 0
        failedTasks.each do |t|
          warning('unscheduled_task',
                  "Task #{t.fullId}: " +
                  "#{t['start', scIdx] ? t['start', scIdx] : '<?>'} -> " +
                  "#{t['end', scIdx] ? t['end', scIdx] : '<?>'}",
                  t.sourceFileInfo)

          i += 1
          break if i >= 10
        end
        Log.stopProgressMeter
        return false
      end

      Log.stopProgressMeter
      Log.exit('scheduleScenario', "Scheduling of scenario #{scIdx} finished")
      true
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.