Codebase list tj3 / a4801c2
New upstream release. Vincent Bernat 3 years ago
126 changed file(s) with 894 addition(s) and 416 deletion(s). Raw diff Collapse all Expand all
432432 background-color:#EE0000;
433433 position:absolute;
434434 }
435 .markdateline {
436 background-color:#000000;
437 position:absolute;
438 }
435439 .white {
436440 background-color:#FFFFFF;
437441 position:absolute;
00 /*
11 * This file contains a project skeleton. It is part of the
22 * TaskJuggler project management tool. You can use this as a basis to
3 * start you own project file.
3 * start your own project file.
44 */
55 project your_project_id "Your Project Title" 2011-11-11-0:00--0500 +4m {
66 # Set the default time zone for the project. If not specified, UTC
2727
2828 # You can define your own attributes for tasks and resources. This
2929 # is handy to capture additional information about the project that
30 # is not directly impacting the project schedule but you like to
30 # is not directly impacting the project schedule, but which you like to
3131 # keep in one place.
3232 #extend task {
3333 # reference spec "Link to Wiki page"
5858 # used to filter out subsets of them during reporting.
5959 flags important, hidden
6060
61 # If you want to do budget planning for you project, you need to
61 # If you want to do budget planning for your project, you need to
6262 # define some accounts.
6363 account cost "Project Cost" {
6464 account dev "Development"
6666 }
6767 account rev "Customer Payments"
6868
69 # The Profit&Loss analysis should be rev - cost accounts.
69 # The Profit & Loss analysis should be rev - cost accounts.
7070 balance cost rev
7171
72 # Define you public holidays here.
72 # Define your public holidays here.
7373 vacation "New Year's Day" 2012-01-02
7474 vacation "Birthday of Martin Luther King, Jr." 2012-01-16
7575 vacation "Washington's Birthday" 2012-02-20
8282 vacation "Christmas Day" 2012-12-25
8383
8484 # The daily default rate of all resources. This can be overridden for each
85 # resource. We specify this, so that we can do a good calculation of
85 # resource. We specify this so we can do a good calculation of
8686 # the costs of the project.
8787 rate 400.0
8888
122122
123123 # Now the project has been specified completely. Stopping here would
124124 # result in a valid TaskJuggler file that could be processed and
125 # scheduled. But no reports would be generated to visualize the
125 # scheduled. Here reports will be generated to visualize the
126126 # results.
127127
128128 navigator navbar {
1919 # used, but this will likely be outside of the project range, so it
2020 # can't be seen in the reports.
2121 now 2002-03-05-13:00
22 # The currency for all money values is the Euro.
22 # The currency for all money values is the US Dollar.
2323 currency "USD"
2424
2525 # We want to compare the baseline scenario to one with a slightly
0 [NAME]
1 tj3 \- schedules tj3 projects and generates reports
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBTASKJUGGLER_DATA_PATH\fR
7 Override the path to the TaskJuggler data folder.
8 The data folder contains the css, icons and scripts
9 for TaskJuggler reports.
10
11 .TP
12 \fBTZ\fR
13 The POSIX Time Zone environment variable.
14
15 Any environment variable may be used in a TaskJuggler file using the expression $(VAR_NAME).
16
17 [EXAMPLES]
18
19 tj3 tutorial.tjp
20
21 [SEE ALSO]
22 tj3client(1), tj3d(1), tj3man(1), tj3ss_receiver(1), tj3ss_sender(1), tj3ts_receiver(1), tj3ts_sender(1), tj3ts_summary(1), tj3webd(1)
23
24 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
0 [NAME]
1 tj3client \- send commands and data to the TaskJuggler daemon
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBHOME\fR
7 The user's home folder. Used to search for configuration file if not specified.
8
9 [FILES]
10
11 .TP
12 \fB.taskjugglerrc\fR or \fBtaskjuggler.rc\fR
13 tj3d searches for a config file named .taskjugglerrc or taskjuggler.rc in the current path, the user's home path as specified by the HOME environment variable or /etc/. At a minimum the file must contain:
14
15 _global:
16 authKey: ********
17
18 (the user should specify their own auth key and set file permissions accordingly). An alternative config file location may be specified using the -c, --config FILE option.
19
20 [EXAMPLES]
21 .TP
22 Load a project:
23 tj3client add yourproject.tjp
24 .PP
25 .TP
26 List available reports for a project:
27 tj3client list-reports <project_id>
28 .PP
29 .TP
30 Generate a report:
31 tj3client report <project_id> <report_id>
32 .PP
33 .TP
34 Terminate a running instance of the server:
35 tj3client terminate
36
37
38
39 [SEE ALSO]
40 tj3d(1)
41
42 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
0 [NAME]
1 tjd3 \- the TaskJuggler daemon
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBHOME\fR
7 The user's home folder. Used to search for configuration file if not specified.
8
9 [FILES]
10
11 .TP
12 \fB.taskjugglerrc\fR or \fBtaskjuggler.rc\fR
13 tj3d searches for a config file named .taskjugglerrc or taskjuggler.rc in the current path, the user's home path as specified by the HOME environment variable or /etc/. At a minimum the file must contain:
14
15 _global:
16 authKey: ********
17
18 (the user should specify their own auth key and set file permissions accordingly). An alternative config file location may be specified using the -c, --config FILE option.
19
20 .TP
21 \fBtj3d.log\fR
22
23 The tj3d log file, created in the working directory. Location can be overridden using the --logfile FILE option.
24
25 [SECURITY]
26 The author advises: "the daemon has not received any kind of security review ... only use the daemon in a trusted environment with only trusted users!"
27
28
29 [SEE ALSO]
30 tj3client(1)
31
32 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
0 [NAME]
1 tj3man \- get documentation for TaskJuggler keywords or generate user manual
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBBROWSER\fR
7 The web browser used to display the user manual as HTML.
8
9 [EXAMPLES]
10
11 tj3man shift
12 .br
13 tj3man --html shift.timesheet
14 .br
15 tj3man --html
16
17 [SEE ALSO]
18
19 tj3(1)
20
21 The TaskJuggler manual is also available online at http://www.taskjuggler.org/tj3/manual/.
0 [NAME]
1 tj3ss_receiver \- receive filled-out status sheets via email
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBHOME\fR
7 The user's home folder. Used to search for configuration file if not specified.
8
9
10 [FILES]
11 .TP
12 \fB.taskjugglerrc\fR or \fBtaskjuggler.rc\fR
13 tj3d searches for a config file named .taskjugglerrc or taskjuggler.rc in the current path, the user's home path as specified by the HOME environment variable or /etc/. At a minimum the file must configure an e-mail delivery method and sender e-mail e.g.:
14
15 _global:
16 emailDeliveryMethod: smtp
17 smtpServer: smtp.your_company.com
18 .br
19 _statussheets:
20 senderEmail: 'TaskJuggler <statussheets@taskjuggler.amd.com>'
21
22 An alternative config file location may be specified using the -c, --config FILE option.
23
24 .TP
25 \fBstatussheets.log\fR
26 The statussheets log file, created in the working directory.
27
28 .TP
29 \fBStatusSheets/FailedMails/\fR
30 Directory created in the working directory to store the failed emails.
31
32 .TP
33 \fBStatusSheets/FailedSheets/\fR
34 Directory created in the working directory to store the failed status sheets.
35
36
37 [SEE ALSO]
38 tj3ss_sender(1)
39
40 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
0 [NAME]
1 tj3ss_sender \- send out status sheets templates via email
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBHOME\fR
7 The user's home folder. Used to search for configuration file if not specified.
8
9
10 [FILES]
11
12 \fB.taskjugglerrc\fR or \fBtaskjuggler.rc\fR
13 tj3d searches for a config file named .taskjugglerrc or taskjuggler.rc in the current path, the user's home path as specified by the HOME environment variable or /etc/. At a minimum the file must configure an authentication key, an e-mail delivery method and sender e-mail e.g.:
14
15 _global:
16 authKey: ********
17 smtpServer: smtp.your_company.com
18 .br
19 _statussheets:
20 senderEmail: 'TaskJuggler <statussheets@taskjuggler.amd.com>'
21
22 (the user should specify their own auth key and set file permissions accordingly). An alternative config file location may be specified using the -c, --config FILE option.
23
24 .TP
25 \fBstatussheets.log\fR
26 The statussheets log file, created in the working directory.
27
28 .TP
29 \fBStatusSheetTemplates\fR
30 Base directory of the sheet templates, created in the working directory.
31
32
33 [SEE ALSO]
34
35 tj3ss_receiver(1), tj3d(1)
36
37 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
0 [NAME]
1 tj3ts_receiver \- receive filled-out time sheets via email
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBHOME\fR
7 The user's home folder. Used to search for configuration file if not specified.
8
9
10 [FILES]
11 .TP
12 \fB.taskjugglerrc\fR or \fBtaskjuggler.rc\fR
13 tj3d searches for a config file named .taskjugglerrc or taskjuggler.rc in the current path, the user's home path as specified by the HOME environment variable or /etc/. At a minimum the file must configure an authentication key, an e-mail delivery method and sender e-mail e.g.:
14
15 _global:
16 authKey: ********
17 smtpServer: smtp.your_company.com
18 _timesheets:
19 senderEmail: 'TaskJuggler <timesheets@taskjuggler.amd.com>'
20
21 (the user should specify their own auth key and set file permissions accordingly). An alternative config file location may be specified using the -c, --config FILE option.
22
23 .TP
24 \fBtimesheets.log\fR
25 The statussheets log file, created in the working directory.
26
27 .TP
28 \fBTimeSheets/FailedMails/\fR
29 Directory created in the working directory to store the failed emails.
30
31 .TP
32 \fBTimeSheets/FailedSheets/\fR
33 Directory created in the working directory to store the failed status sheets.
34
35
36 [SEE ALSO]
37
38 tj3ts_sender(1)
39
40 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
0 [NAME]
1 tj3ts_sender \- send out time sheets templates via email
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBHOME\fR
7 The user's home folder. Used to search for configuration file if not specified.
8
9 [FILES]
10
11 \fB.taskjugglerrc\fR or \fBtaskjuggler.rc\fR
12 tj3d searches for a config file named .taskjugglerrc or taskjuggler.rc in the current path, the user's home path as specified by the HOME environment variable or /etc/. At a minimum the file must configure an authentication key, an e-mail delivery method and sender e-mail e.g.:
13
14 _global:
15 authKey: ********
16 smtpServer: smtp.your_company.com
17 projectId: acso
18 .br
19 _timesheets:
20 senderEmail: 'TaskJuggler <statussheets@taskjuggler.amd.com>'
21
22 (the user should specify their own auth key and set file permissions accordingly). An alternative config file location may be specified using the -c, --config FILE option.
23
24 .TP
25 \fBtimesheets.log\fR
26 The timesheets log file, created in the working directory.
27
28 .TP
29 \fBTimeSheetTemplates\fR
30 Base directory of the sheet templates, created in the working directory.
31
32
33 [SEE ALSO]
34 tj3ts_receiver(1)
35
36 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
0 [NAME]
1 tj3ts_summary \- send out individual copies and a summary of accepted time sheets
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBHOME\fR
7 The user's home folder. Used to search for configuration file if not specified.
8
9
10 [FILES]
11
12 \fB.taskjugglerrc\fR or \fBtaskjuggler.rc\fR
13 tj3d searches for a config file named .taskjugglerrc or taskjuggler.rc in the current path, the user's home path as specified by the HOME environment variable or /etc/. At a minimum the file must configure an authentication key, an e-mail delivery method, project id, sender e-mail and receipients e.g.:
14
15 _global:
16 authKey: ********
17 smtpServer: smtp.your_company.com
18 projectId: acso
19 .br
20 _timesheets:
21 senderEmail: 'TaskJuggler <statussheets@taskjuggler.amd.com>'
22 _summary:
23 sheetRecipients:
24 - team@your_company.com
25
26 (the user should specify their own auth key and set file permissions accordingly). An alternative config file location may be specified using the -c, --config FILE option.
27
28
29 .TP
30 \fBtimesheets.log\fR
31 The timesheets log file, created in the working directory.
32
33 .TP
34 \fBTimeSheetTemplates\fR
35 Base directory of the sheet templates, created in the working directory.
36
37
38 [SEE ALSO]
39 tj3ts_receiver(1) tj3ts_sender(1)
40
41 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
0 [NAME]
1 tj3webd \- TaskJuggler reports web server
2
3 [ENVIRONMENT]
4
5 .TP
6 \fBHOME\fR
7 The user's home folder. Used to search for configuration file if not specified.
8
9 [FILES]
10
11 .TP
12 \fB.taskjugglerrc\fR or \fBtaskjuggler.rc\fR
13 tj3d searches for a config file named .taskjugglerrc or taskjuggler.rc in the current path, the user's home path as specified by the HOME environment variable or /etc/. At a minimum the file must contain:
14
15 _global:
16 authKey: ********
17
18 (the user should specify their own auth key and set file permissions accordingly). An alternative config file location may be specified using the -c, --config FILE option.
19
20 [SEE ALSO]
21 tj3d(1)
22
23 The full TaskJuggler manual is available online at http://www.taskjuggler.org/tj3/manual/, or via the tj3man command.
4949 end
5050
5151 # Set the selection mode identified by name specified in _str_. For
52 # efficiency reasons, we turn the name into a Fixnum value.
52 # efficiency reasons, we turn the name into an Integer value.
5353 def setSelectionMode(str)
5454 modes = %w( order minallocated minloaded maxloaded random )
5555 @selectionMode = modes.index(str)
22 #
33 # = AttributeBase.rb -- The TaskJuggler III Project Management Software
44 #
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2019
66 # by Chris Schlaeger <cs@taskjuggler.org>
77 #
88 # This program is free software; you can redistribute it and/or modify
135135
136136 def to_num
137137 v = get
138 if v.is_a?(Fixnum) || v.is_a?(Bignum) || v.is_a?(Float)
138 if v.is_a?(Integer) || v.is_a?(Float)
139139 v
140140 else
141141 nil
144144
145145 def to_sort
146146 v = get
147 if v.is_a?(Fixnum) || v.is_a?(Bignum) || v.is_a?(Float)
147 if v.is_a?(Integer) || v.is_a?(Float)
148148 v
149149 elsif v.respond_to?('to_s')
150 v.to_s
150 if v.respond_to?('join')
151 # If the attribute is an Array we convert it to a comma separated
152 # list.
153 v.join(', ')
154 else
155 v.to_s
156 end
151157 else
152158 nil
153159 end
263263
264264 end
265265
266 class FixnumAttribute < AttributeBase
267 def initialize(property, type, container)
268 super
269 end
270
271 def FixnumAttribute::tjpId
266 class IntegerAttribute < AttributeBase
267 def initialize(property, type, container)
268 super
269 end
270
271 def IntegerAttribute::tjpId
272272 'integer'
273273 end
274274 end
1515
1616 class TaskJuggler
1717
18 # The JobInfo class is just a storage container for some batch job realted
18 # The JobInfo class is just a storage container for some batch job related
1919 # pieces of information. It contains things like a job id, the process id,
2020 # the stdout data and the like.
2121 class JobInfo
165165 #
166166 # sbStart must be a TjTime of the scoreboard start
167167 # slotDuration must be the duration of the scoreboard slots in seconds
168 # a and b should be TjTime or Fixnum objects that describe the start and
168 # a and b should be TjTime or Integer objects that describe the start and
169169 # end time or index of the interval.
170170 #
171171 # TimeInterval.new(iv)
190190 # If the third argument is a date we convert it to a scoreboard index.
191191 args[2] = dateToIndex(args[2]) if args[2].is_a?(TjTime)
192192
193 if args[2].is_a?(Fixnum) || args[2].is_a?(Bignum)
193 if args[2].is_a?(Integer)
194194 super(args[2], args[2])
195195 else
196196 raise ArgumentError, "Illegal argument 3: #{args[0].class}"
203203 args[2] = dateToIndex(args[2]) if args[2].is_a?(TjTime)
204204 args[3] = dateToIndex(args[3]) if args[3].is_a?(TjTime)
205205
206 if !(args[2].is_a?(Fixnum) || args[2].is_a?(Bignum))
206 if !(args[2].is_a?(Integer))
207207 raise ArgumentError, "Interval start must be an index or TjTime, " +
208208 "not a #{args[2].class}"
209209 end
210 if !(args[3].is_a?(Fixnum) || args[3].is_a?(Bignum))
210 if !(args[3].is_a?(Integer))
211211 raise ArgumentError, "Interval end must be an index or TjTime, " +
212212 "not a #{args[3].class}"
213213 end
220220 raise ArgumentError, "sbStart must be a TjTime object, not a" +
221221 "#{@sbStart.class}"
222222 end
223 unless @slotDuration.is_a?(Fixnum)
224 raise ArgumentError, "slotDuration must be a Fixnum, not a " +
223 unless @slotDuration.is_a?(Integer)
224 raise ArgumentError, "slotDuration must be an Integer, not a " +
225225 "#{@slotDuration.class}"
226226 end
227227
228228 end
229229
230 # Assign the start of the interval. +arg+ can be a Fixnum, Bignum or
230 # Assign the start of the interval. +arg+ can be an Integer or
231231 # TjTime object.
232232 def start=(arg)
233233 case arg
234 when Fixnum
235 when Bignum
234 when Integer
236235 @start = arg
237236 when TjTime
238237 @start = dateToIndex(arg)
241240 end
242241 end
243242
244 # Assign the start of the interval. +arg+ can be a Fixnum, Bignum or
243 # Assign the start of the interval. +arg+ can be an Integer or
245244 # TjTime object.
246245 def end=(arg)
247246 case arg
248 when Fixnum
249 when Bignum
247 when Integer
250248 @end = arg
251249 when TjTime
252250 @end = dateToIndex(arg)
612612 # This function returns a list of entries that have all the exact same
613613 # date and are the last entries before the deadline _date_. Only messages
614614 # with at least the required alert level _minLevel_ are returned. Messages
615 # with alert level _minLevel_ must be newer than _minDate_.
615 # with alert level _minLevel_ or higher must be newer than _minDate_.
616616 def currentEntries(date, property, minLevel, minDate, logExp)
617617 pEntries = getEntries(property) ? getEntries(property).last(date) :
618618 JournalEntryList.new
620620 # date.
621621 pEntries.delete_if do |e|
622622 e.headline.empty? || e.alertLevel < minLevel ||
623 (e.alertLevel == minLevel && minDate && e.date < minDate)
623 (e.alertLevel >= minLevel && minDate && e.date < minDate)
624624 end
625625
626626 unless pEntries.empty?
138138 # 2nd arg must be a scenario index.
139139 return false if (scenarioIdx = project.scenarioIdx(args[1])).nil?
140140 # 3rd arg must be an integer number.
141 return false unless args[2].is_a?(Fixnum)
141 return false unless args[2].is_a?(Integer)
142142
143143 property.isDependencyOf(scenarioIdx, task, args[2])
144144 end
22 #
33 # = LogicalOperation.rb -- The TaskJuggler III Project Management Software
44 #
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2019
66 # by Chris Schlaeger <cs@taskjuggler.org>
77 #
88 # This program is free software; you can redistribute it and/or modify
6363 coerceTime(o, expr)
6464 end
6565 return res
66 elsif opnd1.is_a?(Fixnum) || opnd1.is_a?(Float) || opnd1.is_a?(Bignum)
66 elsif opnd1.is_a?(Integer) || opnd1.is_a?(Float)
6767 return evalBinaryOperation(opnd1, operator, opnd2) do |o|
6868 coerceNumber(o, expr)
6969 end
144144 # An empty String means false, else true.
145145 return !val.empty? if val.is_a?(String)
146146 # In TJP logic 'non 0' means false.
147 return val != 0 if val.is_a?(Fixnum) || val.is_a?(Bignum)
147 return val != 0 if val.is_a?(Integer)
148148
149149 expr.error("Operand #{val} can't be evaluated to true or false.")
150150 end
151151
152152 # Force the _val_ into a number. In case this fails, an exception is raised.
153153 def coerceNumber(val, expr)
154 unless val.is_a?(Fixnum) || val.is_a?(Float) || val.is_a?(Bignum)
154 unless val.is_a?(Integer) || val.is_a?(Float)
155155 expr.error("Operand #{val} of type #{val.class} must be a number.")
156156 end
157157 val
215215 query.scenarioIdx = @scenario.sequenceNo - 1
216216 query.attributeId = @operand1
217217 query.process
218 unless query.ok
219 return "Error in conversion to String: #{query.errorMessage}"
220 end
218221 query.to_s
219222 else
220223 "#{@scenario.fullId}.#{@operand1}"
229229 private
230230
231231 def checkLevel(level)
232 if level.is_a?(Fixnum)
232 if level.is_a?(Integer)
233233 if level < 0 || level > 5
234234 raise ArgumentError, "Unsupported level #{level}"
235235 end
103103 end
104104
105105 # Return the 'index' attributes of this property, prefixed by the 'index'
106 # attributes of all its parents. The result is an Array of Fixnums.
106 # attributes of all its parents. The result is an Array of Integers.
107107 def getIndicies
108108 idcs = []
109109 p = self
7777 'currencyFormat' => RealFormat.new([ '-', '', '', ',', 2 ]),
7878 'dailyworkinghours' => 8.0,
7979 'end' => nil,
80 'markdate' => nil,
8081 'flags' => [],
8182 'journal' => Journal.new,
8283 'limits' => nil,
125126 false, false, false, true ],
126127 [ 'projection', 'Projection Mode', BooleanAttribute,
127128 true, false, false, false ],
128 [ 'seqno', 'No', FixnumAttribute,
129 [ 'seqno', 'No', IntegerAttribute,
129130 false, false, false, nil ],
130131 ]
131132 attrs.each { |a| @scenarios.addAttributeType(AttributeDefinition.new(*a)) }
138139 false, false, false, "" ],
139140 [ 'id', 'ID', StringAttribute,
140141 false, false, false, nil ],
141 [ 'index', 'Index', FixnumAttribute,
142 [ 'index', 'Index', IntegerAttribute,
142143 false, false, false, -1 ],
143144 [ 'leaves', 'Leaves', LeaveListAttribute,
144145 true, true, true, LeaveList.new ],
146147 false, false, false, nil ],
147148 [ 'replace', 'Replace', BooleanAttribute,
148149 true, false, true, false ],
149 [ 'seqno', 'No', FixnumAttribute,
150 [ 'seqno', 'No', IntegerAttribute,
150151 false, false, false, nil ],
151152 [ 'timezone', 'Time Zone', StringAttribute,
152153 true, true, true, TjTime.timeZone ],
169170 false, false, true, [] ],
170171 [ 'id', 'ID', StringAttribute,
171172 false, false, false, nil ],
172 [ 'index', 'Index', FixnumAttribute,
173 [ 'index', 'Index', IntegerAttribute,
173174 false, false, false, -1 ],
174175 [ 'flags', 'Flags', FlagListAttribute,
175176 true, false, true, [] ],
176177 [ 'name', 'Name', StringAttribute,
177178 false, false, false, nil ],
178 [ 'seqno', 'No', FixnumAttribute,
179 [ 'seqno', 'No', IntegerAttribute,
179180 false, false, false, nil ],
180181 [ 'tree', 'Tree Index', StringAttribute,
181182 false, false, false, "" ]
200201 false, false, true, [] ],
201202 [ 'efficiency','Efficiency', FloatAttribute,
202203 true, false, true, 1.0 ],
203 [ 'effort', 'Total Effort', FixnumAttribute,
204 [ 'effort', 'Total Effort', IntegerAttribute,
204205 false, false, true, 0 ],
205206 [ 'email', 'Email', StringAttribute,
206207 false, false, false, nil ],
208209 false, false, false, [] ],
209210 [ 'flags', 'Flags', FlagListAttribute,
210211 true, false, true, [] ],
211 [ 'index', 'Index', FixnumAttribute,
212 [ 'index', 'Index', IntegerAttribute,
212213 false, false, false, -1 ],
213214 [ 'leaveallowances', 'Leave Allowances', LeaveAllowanceListAttribute,
214215 true, false, true, LeaveAllowanceList.new ],
222223 true, true, true, 0.0 ],
223224 [ 'reports', 'Reports', ResourceListAttribute,
224225 false, false, true, [] ],
225 [ 'seqno', 'No', FixnumAttribute,
226 [ 'seqno', 'No', IntegerAttribute,
226227 false, false, false, nil ],
227228 [ 'shifts', 'Shifts', ShiftAssignmentsAttribute,
228229 true, false, true, nil ],
263264 false, false, true, 0 ],
264265 [ 'effort', 'Effort', DurationAttribute,
265266 false, false, true, 0 ],
266 [ 'effortdone', 'Completed Effort', FixnumAttribute,
267 [ 'effortdone', 'Completed Effort', IntegerAttribute,
267268 false, false, true, nil ],
268 [ 'effortleft', 'Remaining Effort', FixnumAttribute,
269 [ 'effortleft', 'Remaining Effort', IntegerAttribute,
269270 false, false, true, nil ],
270271 [ 'end', 'End', DateAttribute,
271272 false, false, true, nil ],
283284 false, false, true, nil ],
284285 [ 'id', 'ID', StringAttribute,
285286 false, false, false, nil ],
286 [ 'index', 'Index', FixnumAttribute,
287 [ 'index', 'Index', IntegerAttribute,
287288 false, false, false, -1 ],
288289 [ 'length', 'Length', DurationAttribute,
289290 false, false, true, 0 ],
307308 false, false, true, 0.0 ],
308309 [ 'precedes', 'Following tasks', DependencyListAttribute,
309310 true, false, true, [] ],
310 [ 'priority', 'Priority', FixnumAttribute,
311 [ 'priority', 'Priority', IntegerAttribute,
311312 true, true, true, 500 ],
312313 [ 'projectid', 'Project ID', SymbolAttribute,
313314 true, true, true, nil ],
317318 true, false, true, false ],
318319 [ 'projectionmode', 'Projection Mode', BooleanAttribute,
319320 true, false, true, false ],
320 [ 'seqno', 'No', FixnumAttribute,
321 [ 'seqno', 'No', IntegerAttribute,
321322 false, false, false, nil ],
322323 [ 'shifts', 'Shifts', ShiftAssignmentsAttribute,
323324 true, false, true, nil ],
360361 true, false, false, KeywordArray.new([ '*' ]) ],
361362 [ 'end', 'End', DateAttribute,
362363 true, true, false, nil ],
364 [ 'markdate', 'Markdate', DateAttribute,
365 true, true, false, nil ],
363366 [ 'epilog', 'Epilog', RichTextAttribute,
364367 true, false, false, nil ],
365368 [ 'flags', 'Flags', FlagListAttribute,
382385 true, false, false, nil ],
383386 [ 'hideTask', 'Hide Task', LogicalExpressionAttribute,
384387 true, false, false, nil ],
385 [ 'height', 'Height', FixnumAttribute,
388 [ 'height', 'Height', IntegerAttribute,
386389 false, false, false, 480 ],
387390 [ 'id', 'ID', StringAttribute,
388391 false, false, false, nil ],
389 [ 'index', 'Index', FixnumAttribute,
392 [ 'index', 'Index', IntegerAttribute,
390393 false, false, false, -1 ],
391394 [ 'interactive', 'Interactive', BooleanAttribute,
392395 false, false, false, false ],
428431 true, false, false, [ 0 ] ],
429432 [ 'selfcontained', 'Selfcontained', BooleanAttribute,
430433 true, false, false, false ],
431 [ 'seqno', 'No', FixnumAttribute,
434 [ 'seqno', 'No', IntegerAttribute,
432435 false, false, false, nil ],
433436 [ 'shortTimeFormat', 'Short Time Format', StringAttribute,
434437 true, true, false, nil ],
460463 false, false, false, "" ],
461464 [ 'weekStartsMonday', 'Week Starts Monday', BooleanAttribute,
462465 true, true, false, false ],
463 [ 'width', 'Width', FixnumAttribute,
464 true, false, false, 640 ]
466 [ 'width', 'Width', IntegerAttribute,
467 true, false, false, 640 ],
468 [ 'novevents', 'No vevents in icalreports', BooleanAttribute,
469 true, false, false, false ]
465470 ]
466471 attrs.each { |a| @reports.addAttributeType(AttributeDefinition.new(*a)) }
467472
559564 #
560565 # Return the Scenario with the given _id_ or _index_.
561566 def scenario(arg)
562 if arg.is_a?(Fixnum)
567 if arg.is_a?(Integer)
563568 @scenarios.each do |sc|
564569 return sc if sc.sequenceNo - 1 == arg
565570 end
865870 # isWorkingTime(startTime, endTime) -> true or false
866871 # isWorkingTime(interval) -> true or false
867872 #
868 # Return true if the slot or interval is withing globally defined working
873 # Return true if the slot or interval is within globally defined working
869874 # time or false if not. If the argument is a TimeInterval, all slots of
870875 # the interval must be working time to return true as result. Global work
871876 # time means, no global leaves defined and the slot lies within a
873878 def isWorkingTime(*args)
874879 # Normalize argument(s) to TimeInterval
875880 if args.length == 1
876 if args[0].is_a?(Fixnum) || args[0].is_a?(Bignum)
881 if args[0].is_a?(Integer)
877882 return @scoreboard[args[0]].nil?
878883 elsif args[0].is_a?(TjTime)
879884 return @scoreboard[dateToIdx(args[0])].nil?
968973
969974 def collectTimeOffIntervals(iv, minDuration)
970975 @scoreboard.collectIntervals(iv, minDuration) do |val|
971 val.is_a?(Fixnum) && (val & 0x3E) != 0
976 val.is_a?(Integer) && (val & 0x3E) != 0
972977 end
973978 end
974979
22 #
33 # = PropertyList.rb -- The TaskJuggler III Project Management Software
44 #
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2019
66 # by Chris Schlaeger <cs@taskjuggler.org>
77 #
88 # This program is free software; you can redistribute it and/or modify
270270
271271 @query.property = a
272272 @query.process
273 unless @query.ok
274 fatal "List sort failed: #{@query.errorMessage}"
275 end
273276 aVal = @query.to_sort
274277
275278 @query.property = b
276279 @query.process
280 unless @query.ok
281 fatal "List sort failed: #{@query.errorMessage}"
282 end
277283 bVal = @query.to_sort
278284 else
279285 # In case we don't have a query, we use the static mechanism.
5050 [
5151 [ 'id', 'ID', StringAttribute, false, false, false, '' ],
5252 [ 'name', 'Name', StringAttribute, false, false, false, '' ],
53 [ 'seqno', 'Seq. No', FixnumAttribute, false, false, false, 0 ]
53 [ 'seqno', 'Seq. No', IntegerAttribute, false, false, false, 0 ]
5454 ].each { |a| addAttributeType(AttributeDefinition.new(*a)) }
5555 end
5656
22 #
33 # = PropertyTreeNode.rb -- The TaskJuggler III Project Management Software
44 #
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2019
66 # by Chris Schlaeger <cs@taskjuggler.org>
77 #
88 # This program is free software; you can redistribute it and/or modify
330330 end
331331
332332 # Return the 'index' attributes of this property, prefixed by the 'index'
333 # attributes of all its parents. The result is an Array of Fixnums.
333 # attributes of all its parents. The result is an Array of Integers.
334334 def getIndicies
335335 idcs = []
336336 p = self
701701 res += '-' * 75 + "\n"
702702 end
703703
704 alias to_str to_s
705
704706 # Many PropertyTreeNode functions are scenario specific. These functions are
705707 # provided by the class *Scenario classes. In case we can't find a function
706708 # called for the base class we try to find it in corresponding *Scenario
707709 # class.
708 def method_missing(func, scenarioIdx, *args, &block)
710 def method_missing(func, scenarioIdx = 0, *args, &block)
709711 @data[scenarioIdx].send(func, *args, &block)
710712 end
711713
8080 end
8181
8282 def startIdx=(idx)
83 if idx.is_a?(Fixnum)
83 if idx.is_a?(Integer)
8484 @startIdx = idx
8585 @start = @project.idxToDate(idx)
8686 else
9898 end
9999
100100 def endIdx=(idx)
101 if idx.is_a?(Fixnum)
101 if idx.is_a?(Integer)
102102 @endIdx = idx
103103 @end = @project.idxToDate(idx)
104104 else
238238 @attr ? @attr.to_s(self) : (@rti ? @rti.to_s : (@string || ''))
239239 end
240240
241 # Return the result of the Query as Fixnum or Float. The result may be
241 # Return the result of the Query as Integer or Float. The result may be
242242 # nil.
243243 def to_num
244244 @attr ? @attr.to_num : @numerical
2323 # thousandsSeparator: Separator used after 3 integer digits. (String)
2424 # fractionSeparator: Separator used between the inter part and the
2525 # fractional part. (String)
26 # fractionDigits: Number of fractional digits to show. (Fixnum)
26 # fractionDigits: Number of fractional digits to show. (Integer)
2727 class RealFormat
2828
2929 attr_reader :signPrefix, :signSuffix, :thousandsSeparator,
22 #
33 # = Resource.rb -- The TaskJuggler III Project Management Software
44 #
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2019
66 # by Chris Schlaeger <cs@taskjuggler.org>
77 #
88 # This program is free software; you can redistribute it and/or modify
3636 # provided by the class ResourceScenario. In case we can't find a
3737 # function called for the Resource class we try to find it in
3838 # ResourceScenario.
39 def method_missing(func, scenarioIdx, *args, &block)
39 def method_missing(func, scenarioIdx = 0, *args, &block)
4040 @data[scenarioIdx].method(func).call(*args, &block)
4141 end
4242
1919 def initialize(resource, scenarioIdx, attributes)
2020 super
2121
22 # Scoreboard may be nil, a Task, or a bit vector encoded as a Fixnum
22 # Scoreboard may be nil, a Task, or a bit vector encoded as an Integer
2323 # nil: Value has not been determined yet.
2424 # Task: A reference to a Task object
2525 # Bit 0: Reserved
276276 query.sortable = query.numerical = val =
277277 getLeave(query.startIdx, query.endIdx, :annual)
278278 query.string = query.scaleLoad(val)
279 end
280
281 # Compute a list of the annual leave days within the period specified by
282 # the _query_. The result is a list of dates and how much of that day was
283 # taken.
284 def query_annualleavelist(query)
285 iv_list = collectLeaveIntervals(Interval.new(query.start, query.end), :annual)
286 iv_list.map! do |iv|
287 # The interval is at most one working day. We list the date of that
288 # day.
289 day = iv.start.strftime(@project['timeFormat'])
290 # And how much of the working day was taken. A full working day is
291 # 1.0, a half working day 0.5.
292 days = (iv.end - iv.start) / (60 * 60 * @project['dailyworkinghours'])
293 "#{day} (#{'%.1f' % days})"
294 end
295 query.assignList(iv_list)
279296 end
280297
281298 def query_annualleavebalance(query)
684701 initScoreboard if @scoreboard.nil?
685702
686703 @scoreboard.collectIntervals(iv, minDuration) do |val|
687 val.is_a?(Fixnum) && (val & 0x3E) != 0
704 val.is_a?(Integer) && (val & 0x3E) != 0
705 end
706 end
707
708 # Return a list of scoreboard intervals that are at least _minDuration_ long
709 # and only contain leave slots of the given type. The result is an Array of
710 # [ start, end ] TjTime values.
711 def collectLeaveIntervals(iv, type)
712 # Time-off intervals are only useful for leaf resources. Group resources
713 # would just default to the global working hours.
714 return [] unless @property.leaf?
715
716 initScoreboard if @scoreboard.nil?
717
718 @scoreboard.collectIntervals(iv, 60 * 60) do |val|
719 val.is_a?(Integer) && (val & 0x3E) == (Leave::Types[type] << 2)
688720 end
689721 end
690722
722754 # leave.
723755 def getLeaveSlots(startIdx, endIdx, type)
724756 countSlots(startIdx, endIdx) do |val|
725 val.is_a?(Fixnum) && (val & 0x3E) == (Leave::Types[type] << 2)
757 val.is_a?(Integer) && (val & 0x3E) == (Leave::Types[type] << 2)
726758 end
727759 end
728760
738770 def getTimeOffSlots(startIdx, endIdx)
739771 countSlots(startIdx, endIdx) do |val|
740772 # Bit 1 needs to be unset and the leave bits must not be 0.
741 val.is_a?(Fixnum) && (val & 0x2) == 0 && (val & 0x3C) != 0
773 val.is_a?(Integer) && (val & 0x2) == 0 && (val & 0x3C) != 0
742774 end
743775 end
744776
899931 initScoreboard unless @scoreboard
900932
901933 val = @scoreboard[sbIdx]
902 return true unless val.is_a?(Fixnum)
934 return true unless val.is_a?(Integer)
903935
904936 leave_type = (val >> 2) & 0xF
905937 leave_type < Leave::Types[:unemployed]
2626
2727 # Create a RichTextSnip object. _document_ is a reference to the
2828 # RichTextDocument. _fileName_ is the name of the structured text file
29 # using RichText syntax. _sectionCounter_ is an 3 item Fixnum Array. These
29 # using RichText syntax. _sectionCounter_ is an 3 item Integer Array. These
3030 # 3 numbers are used to store the section counters over multiple
3131 # RichTextSnip objects.
3232 def initialize(document, fileName, sectionCounter)
4444 def configure(object, section)
4545 debug("Configuring object of type #{object.class}")
4646 sections = section.split('.')
47 p = @config
47 return false unless (p = @config)
4848 sections.each do |sec|
4949 p = p['_' + sec]
5050 unless p
22 #
33 # = Scoreboard.rb -- The TaskJuggler III Project Management Software
44 #
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2019
66 # by Chris Schlaeger <cs@taskjuggler.org>
77 #
88 # This program is free software; you can redistribute it and/or modify
174174 end
175175
176176 def inspect
177 s = ''
177178 0.upto(@sb.length - 1) do |i|
178 puts "#{idxToDate(i)}: #{@sb[i]}"
179 s << "#{idxToDate(i)}: #{@sb[i]}"
179180 end
181
182 s
180183 end
181184
182185 end
22 #
33 # = Shift.rb -- The TaskJuggler III Project Management Software
44 #
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2019
66 # by Chris Schlaeger <cs@taskjuggler.org>
77 #
88 # This program is free software; you can redistribute it and/or modify
3333 # provided by the class ShiftScenario. In case we can't find a
3434 # function called for the Shift class we try to find it in
3535 # ShiftScenario.
36 def method_missing(func, scenarioIdx, *args)
36 def method_missing(func, scenarioIdx = 0, *args)
3737 @data[scenarioIdx].method(func).call(*args)
3838 end
3939
7878 # To optimize memory usage and computation time the Scoreboard objects for
7979 # similar ShiftAssignments are shared.
8080 #
81 # Scoreboard may be nil or a bit vector encoded as a Fixnum
81 # Scoreboard may be nil or a bit vector encoded as an Integer
8282 # nil: Value has not been determined yet.
8383 # Bit 0: 0: No assignment
8484 # 1: Has assignement
2828 attr_accessor :maxCpuCores, :warnTsDeltas, :generateTraces
2929
3030 # Create a new TaskJuggler object. _console_ is a boolean that determines
31 # whether or not messsages can be written to $stderr.
31 # whether or not messages can be written to $stderr.
3232 def initialize
3333 @project = nil
3434 @parser = nil
140140 res
141141 end
142142
143 # Generate all specified reports. The project must have be scheduled before
143 # Generate all specified reports. The project must have been scheduled before
144144 # this method can be called. It returns true if no error occured, false
145145 # otherwise.
146146 def generateReports(outputDir = nil)
288288 end
289289
290290 # Check the content of the file _fileName_ and interpret it as a time sheet.
291 # If the sheet is syntaxtically correct and matches the loaded project, true
291 # If the sheet is syntactically correct and matches the loaded project, true
292292 # is returned. Otherwise false.
293293 def checkTimeSheet(fileName)
294294 begin
332332 end
333333
334334 # Check the content of the file _fileName_ and interpret it as a status
335 # sheet. If the sheet is syntaxtically correct and matches the loaded
335 # sheet. If the sheet is syntactically correct and matches the loaded
336336 # project, true is returned. Otherwise false.
337337 def checkStatusSheet(fileName)
338338 begin
4242
4343 # This class is used to handle the low-level input operations. It knows
4444 # whether it deals with a text buffer or a file and abstracts this to the
45 # Scanner. For each nested file the scanner puts an StreamHandle on the
45 # Scanner. For each nested file the scanner puts a StreamHandle on the
4646 # stack while the file is scanned. With this stack the scanner can resume
47 # the processing of the enclosing file once the included files has been
47 # the processing of the enclosing file once the included files have been
4848 # completely processed.
4949 class StreamHandle
5050
280280 end
281281
282282
283 # Start the processing. if _fileNameIsBuffer_ is true, we operate on a
283 # Start the processing. If _fileNameIsBuffer_ is true, we operate on a
284284 # String, else on a File.
285285 def open(fileNameIsBuffer = false)
286286 @fileNameIsBuffer = fileNameIsBuffer
122122 # Add a new rule to the rule set. _name_ must be a unique identifier. The
123123 # function also sets the class variable @cr to the new rule. Subsequent
124124 # calls to TextParser#pattern, TextParser#optional or
125 # TextParser#repeatable will then implicitely operate on the most recently
125 # TextParser#repeatable will then implicitly operate on the most recently
126126 # added rule.
127127 def newRule(name)
128128 # Use a symbol instead of a String.
4545 @sourceFileInfo = nil
4646 end
4747
48 # Store the number of worked time slots. If the value is a Fixnum, it can
48 # Store the number of worked time slots. If the value is an Integer, it can
4949 # be directly assigned. A Float is interpreted as percentage and must be
5050 # in the rage of 0.0 to 1.0.
5151 def work=(value)
52 if value.is_a?(Fixnum)
52 if value.is_a?(Integer)
5353 @work = value
5454 else
5555 # Must be percent value
5050 @opts.summary_width = @optsSummaryWidth
5151 @opts.summary_indent = ' ' * @optsSummaryIndent
5252
53 @opts.banner = "#{AppConfig.softwareName} v#{AppConfig.version} - " +
54 "#{AppConfig.packageInfo}\n\n" +
55 "Copyright (c) #{AppConfig.copyright.join(', ')}\n" +
53 @opts.banner = "Copyright (c) #{AppConfig.copyright.join(', ')}\n" +
5654 " by #{AppConfig.authors.join(', ')}\n\n" +
5755 "#{AppConfig.license}\n" +
5856 "For more info about #{AppConfig.softwareName} see " +
5957 "#{AppConfig.contact}\n\n" +
6058 "Usage: #{AppConfig.appName} [options] " +
6159 "#{@mandatoryArgs}\n\n"
62 @opts.separator ""
60
61 @opts.separator "\nOptions:"
6362 @opts.on('-c', '--config <FILE>', String,
6463 format('Use the specified YAML configuration file')) do |arg|
6564 @configFile = arg
7473 format(<<'EOT'
7574 Don't use ANSI contol sequences to color the terminal output. Colors should
7675 only be used when spooling to an ANSI terminal. In case the detection fails,
77 you can this option to force colors to be off.
76 you can use this option to force colors to be off.
7877 EOT
7978 )) do
8079 Term::ANSIColor::coloring = false
9089 quit
9190 end
9291 @opts.on_tail('--version', format('Show version info')) do
93 puts "#{AppConfig.softwareName} v#{AppConfig.version} - " +
94 "#{AppConfig.packageInfo}"
92 # Display the software name and version in GNU format
93 # as expected by help2man
94 # https://www.gnu.org/prep/standards/standards.html#g_t_002d_002dversion
95 puts "#{AppConfig.appName} (#{AppConfig.softwareName}) #{AppConfig.version}\n"
96 # To also display the copyright and license statements in GNU format
97 # uncomment the following and remove the equivalent statements from
98 # --help
99 # +
100 #<<'EOT'
101 #Copyright (C) 2016 Chris Schlaeger <cs@taskjuggler.org>
102 #License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>
103 #This is free software; you can redistribute it and/or modify it under
104 #the terms of version 2 of the GNU General Public License as published by the
105 #Free Software Foundation.
106 #
107 #For more info about TaskJuggler see http://www.taskjuggler.org
108 #EOT
95109 quit
96110 end
97111
127141 args = processArguments(argv)
128142
129143 # If DEBUG mode has been enabled, we restore the INT trap handler again
130 # to get Ruby backtrackes.
144 # to get Ruby backtraces.
131145 Kernel.trap('INT', intHandler) if $DEBUG
132146
133147 unless @silent
145159 retVal = appMain(args)
146160 MessageHandlerInstance.instance.trapSetup = false
147161 rescue TjRuntimeError
148 # We have hit a sitatuation that we can't recover from. A message
162 # We have hit a situation that we can't recover from. A message
149163 # was severed via the MessageHandler to inform the user and we now
150164 # abort the program.
151165 return 1
22 #
33 # = Tj3Config.rb -- The TaskJuggler III Project Management Software
44 #
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016
5 # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016,
6 # 2020
67 # by Chris Schlaeger <cs@taskjuggler.org>
78 #
89 # This program is free software; you can redistribute it and/or modify
1213
1314 require 'taskjuggler/UTF8String'
1415 require 'taskjuggler/AppConfig'
16 require 'taskjuggler/version'
1517
16 AppConfig.version = '3.6.0'
18 AppConfig.version = VERSION
1719 AppConfig.packageName = 'taskjuggler'
1820 AppConfig.softwareName = 'TaskJuggler'
1921 AppConfig.packageInfo = 'A Project Management Software'
20 AppConfig.copyright = [ (2006..2016).to_a ]
22 AppConfig.copyright = [ (2006..2020).to_a ]
2123 AppConfig.authors = [ 'Chris Schlaeger <cs@taskjuggler.org>' ]
2224 AppConfig.contact = 'http://www.taskjuggler.org'
2325 AppConfig.license = <<'EOT'
7474 @file.each_line do |line|
7575 if line[0, mark.length] == mark
7676 # We've found an annotation line. Get the tag and indicator.
77 dum, dum, dum, tag, indicator = line.split
77 tokens = line.split
78 tag = tokens[3]
79 indicator = tokens[4]
7880
7981 if indicator == '+'
8082 # Start a new snip
7575 def rule_accountHeader
7676 pattern(%w( _account !optionalID $STRING ), lambda {
7777 if @property.nil? && !@accountprefix.empty?
78 @property = @project.accout(@accountprefix)
78 @property = @project.account(@accountprefix)
7979 end
8080 if @val[1] && @project.account(@val[1])
8181 error('account_exists', "Account #{@val[1]} has already been defined.",
238238 inherited allocations or flags.
239239
240240 For effort-based tasks the task duration is clipped to only extend from the
241 begining of the first allocation to the end of the last allocation. This is
241 beginning of the first allocation to the end of the last allocation. This is
242242 done to optimize for an overall minimum project duration as dependent tasks
243243 can potentially use the unallocated, clipped slots.
244244 EOT
286286 @allocate.setSelectionMode(@val[1])
287287 })
288288 doc('select', <<'EOT'
289 The select functions controls which resource is picked from an allocation and
289 The select function controls which resource is picked from an allocation and
290290 it's alternatives. The selection is re-evaluated each time the resource used
291291 in the previous time slot becomes unavailable.
292292
300300 @allocate.persistent = true
301301 })
302302 doc('persistent', <<'EOT'
303 Specifies that once a resource is picked from the list of alternatives this
303 Specifies that once a resource is picked from the list of alternatives, this
304304 resource is used for the whole task. This is useful when several alternative
305305 resources have been specified. Normally the selected resource can change after
306306 each break. A break is an interval of at least one timeslot where no resources
388388 descr(<<'EOT'
389389 Pick the resource that has the smallest allocation factor. The
390390 allocation factor is calculated from the various allocations of the resource
391 across the tasks. This is the default setting.)
391 across the tasks. This is the default setting.
392392 EOT
393393 )
394394
747747 Normally, columns with calculated values take the specified report period into
748748 account when calculating their values. With this attribute, the user can
749749 specify an end date for the period that should be used when calculating the
750 values of this column. It does not have an impact on column with time
750 values of this column. It does not have an impact on columns with time
751751 invariant values.
752752 EOT
753753 )
780780 @column.listItem = @val[1]
781781 })
782782 doc('listitem.column', <<'EOT'
783 Specifies a RichText pattern that is used to generate the text for the list
783 Specifies a [[Rich_Text_Attributes|Rich Text]] pattern that is used to generate the text for the list
784784 items. The pattern should contain at least one ''''<nowiki><</nowiki>-query
785785 attribute='XXX'->'''' element that will be replaced with the value of
786786 attribute XXX. For the replacement, the property of the query will be the list
823823 Normally, columns with calculated values take the specified report period into
824824 account when calculating their values. With this attribute, the user can
825825 specify a start date for the period that should be used when calculating the
826 values of this column. It does not have an impact on column with time
826 values of this column. It does not have an impact on columns with time
827827 invariant values.
828828 EOT
829829 )
929929 ''''+HHMM'''' or ''''-HHMM''''. Dates must always be aligned with the
930930 [[timingresolution]].
931931
932 TaskJuggler also supports simple date calculations. You can add or substract a
932 TaskJuggler also supports simple date calculations. You can add or subtract a
933933 given interval from a fixed date.
934934
935935 %{2009-11-01 + 8m}
936936
937 This will result in an actual date of around 2009-07-01. Keep in mind that due
937 This will result in an actual date of around 2010-07-01. Keep in mind that due
938938 to the varying lengths of months TaskJuggler cannot add exactly 8 calendar
939939 months. The date calculation functionality makes most sense when used with
940940 macros.
941941
942942 %{${now} - 2w}
943943
944 This is result in a date 2 weeks earlier than the current (or specified) date.
944 This results in a date 2 weeks earlier than the current (or specified) date.
945945 See [[duration]] for a complete list of supported time intervals. Don't forget
946946 to put at least one space character after the date to prevent TaskJuggler from
947947 interpreting the interval as an hour.
10641064 @property.set('definitions', @val[1])
10651065 })
10661066 doc('definitions', <<"EOT"
1067 This attributes controls what definitions will be contained in the report. If
1067 This attribute controls what definitions will be contained in the report. If
10681068 the list includes ''project'', the generated file will have a ''''.tjp''''
10691069 extension. Otherwise it will have a ''''.tji'''' extension.
10701070
1071 By default, the report contains everything and the generated files has a ''''.tjp'''' extension.
1071 By default, the report contains everything and the generated files have a ''''.tjp'''' extension.
10721072 EOT
10731073 )
10741074 allOrNothingListRule('exportDefinitions',
11871187 descr(<<'EOT'
11881188 Export of the scheduled project in Microsoft Project XML format. This will
11891189 export the data of the fully scheduled project. The exported data include the
1190 tasks, resources and the assignments of resources to task. This is only a
1190 tasks, resources and the assignments of resources to tasks. This is only a
11911191 small subset of the data that TaskJuggler can manage. This export is intended
11921192 to share resource assignment data with other teams using Microsoft Project.
1193 TaskJuggler manages assignments with a larger accuracy than the Microsft
1193 TaskJuggler manages assignments with a larger accuracy than the Microsoft
11941194 Project XML format can represent. This will inevitably lead to some rounding
11951195 errors and different interpretation of the data. The numbers you will see in
1196 Project are not necessarily an exact match of the numbers you see in
1196 Microsoft Project are not necessarily an exact match of the numbers you see in
11971197 TaskJuggler. The XML file format requires the sequence of the tasks in the
11981198 file to follow the work breakdown structure. Hence all user provided sorting
11991199 directions will be ignored for this format.
13841384
13851385 singlePattern('_inherit')
13861386 doc('inherit.extend', <<'EOT'
1387 If the this attribute is used, the property extension will be inherited by
1387 If this attribute is used, the property extension will be inherited by
13881388 child properties from their parent property.
13891389 EOT
13901390 )
14561456 operations. The final result of a logical expression is always true or false.
14571457 Logical expressions are used the reduce the properties in a report to a
14581458 certain subset or to select alternatives for the cell content of a table. When
1459 used with attributes like [[hidejournalentry]] the logical expression
1459 the logical expression is used with attributes like [[hidejournalentry]] and
14601460 evaluates to true for a certain property, this property is hidden or rolled-up
14611461 in the report.
14621462
15061506 })
15071507 arg(0, 'operand', <<'EOT'
15081508 An operand is a declared flag. An operand can be a negated operand by
1509 prefixing a ~ charater or it can be another logical expression enclosed in
1509 prefixing a ~ character or it can be another logical expression enclosed in
15101510 braces.
15111511 EOT
15121512 )
15261526 })
15271527 arg(1, 'operand', <<'EOT'
15281528 An operand is a declared flag. An operand can be a negated operand by
1529 prefixing a ~ charater or it can be another logical expression enclosed in
1529 prefixing a ~ character or it can be another logical expression enclosed in
15301530 braces.
15311531 EOT
15321532 )
15811581
15821582 All functions may operate on the current property and the scope property. The
15831583 scope property is the enclosing property in reports with nested properties.
1584 Imagine e. g a task report with nested resources. When the function is called
1584 Imagine e. g. a task report with nested resources. When the function is called
15851585 for a task line, the task is the property and we don't have a scope property.
15861586 When the function is called for a resource line, the resource is the property
15871587 and the enclosing task is the scope property.
15881588
1589 These number of arguments that are passed in brackets to the function depends
1589 The number of arguments that are passed in brackets to the function depends
15901590 on the specific function. See the reference for details on each function.
15911591
15921592 All functions can be suffixed with an underscore character. In that case, the
15931593 function is operating on the scope property as if it were the property. The
15941594 original property is ignored in that case. In our task report example from
1595 above, calling a function with an appended dash would mean that a task
1595 above, calling a function with an appended underscore would mean that a task
15961596 line would be evaluated for the enclosing resource.
15971597
15981598 In the example below you can see how this can be used. To generate a task
16831683
16841684 pattern(%w( _isongoing _( $ID _) ))
16851685 doc('isongoing', <<'EOT'
1686 Will evaluate to true for tasks that overlap with the report period in given
1686 Will evaluate to true for tasks that overlap with the report period in the given
16871687 scenario.
16881688 EOT
16891689 )
18241824 pattern(%w( !reportStart ))
18251825 pattern(%w( !rollupresource ))
18261826 pattern(%w( !rolluptask ))
1827 pattern(%w( _novevents), lambda { @property.set('novevents', [ true ]) })
1828 doc('novevents', <<'EOT'
1829 Don't add VEVENT entries to generated [[icalreport]]s.
1830 EOT
1831 )
18271832
18281833 pattern(%w( _scenario !scenarioId ), lambda {
18291834 # Don't include disabled scenarios in the report
18361841 end
18371842 })
18381843 doc('scenario.ical', <<'EOT'
1839 Id of the scenario that should be included in the report. By default, the
1840 top-level scenario will be included. This attribute can be used select another
1844 ID of the scenario that should be included in the report. By default, the
1845 top-level scenario will be included. This attribute can be used to select another
18411846 scenario.
18421847 EOT
18431848 )
18621867 # Show all journal entries.
18631868 @property.set('hideJournalEntry',
18641869 LogicalExpression.new(LogicalOperation.new(0)))
1870 # Add VEVENT entries to icalreports by default
1871 @property.set('novevents', [ false ])
18651872 end
18661873 })
18671874 arg(1, 'file name', <<'EOT'
20202027 end date without a time is expanded to midnight that day. So the day of the
20212028 end date is not included in the interval! The start and end dates must be separated by a hyphen character.
20222029
2023 In the second form specifies the start date and an interval duration. The
2030 The second form specifies the start date and an interval duration. The
20242031 duration must be prefixed by a plus character.
20252032 EOT
20262033 )
21602167 pattern(%w( _alerts_dep ), lambda { :alerts_dep })
21612168 descr(<<'EOT'
21622169 In this mode only the last entries before the report end date for the context
2163 property and all its sub-properties and their dependencies is included. If
2170 property and all its sub-properties and their dependencies are included. If
21642171 there are multiple entries at the exact same date, then all these entries are
21652172 included. In contrast to the ''''status_down'''' mode, only entries with an
21662173 alert level above the default level, and only those with the highest overall
21892196 during the project. Depending on the context, a journal entry may or may not
21902197 be associated with a specific property or author.
21912198
2192 A journal entry can consists of up to three parts. The headline is mandatory
2199 A journal entry can consist of up to three parts. The headline is mandatory
21932200 and should be only 5 to 10 words long. The introduction is optional and should
21942201 be only one or two sentences long. All other details should be put into the
21952202 third part.
22082215 @journalEntry.alertLevel = @val[1]
22092216 })
22102217 doc('alert', <<'EOT'
2211 Specify the alert level for this entry. This attribute is inteded to be used for
2218 Specify the alert level for this entry. This attribute is intended to be used for
22122219 status reporting. When used for a journal entry that is associated with a
22132220 property, the value can be reported in the alert column. When multiple entries
22142221 have been specified for the property, the entry with the date closest to the
23292336 used to report the current annual leave balance.
23302337
23312338 Leaves outside of the project period are silently ignored and will not be
2332 considered in the leave balance calculation. Therefor, leave allowances are
2339 considered in the leave balance calculation. Therefore, leave allowances are
23332340 only allowed within the project period.
23342341 EOT
23352342 )
23512358 and intervals may overlap. The leave types have different priorities. A higher
23522359 priority leave type can overwrite a lower priority type. This means that
23532360 resource level leaves can overwrite global leaves when they have a higher
2354 priority. A sub resource can overwrite a leave of a enclosing resource.
2361 priority. A sub resource can overwrite a leave of an enclosing resource.
23552362
23562363 Leave periods outside of the project interval are silently ignored. For leave
23572364 periods that are partially outside of the project period only the part inside
24682475 doc('dailymin', <<'EOT'
24692476 Minimum required effort for any calendar day. This value cannot be guaranteed by
24702477 the scheduler. It is only checked after the schedule is complete. In case the
2471 minium required amount has not been reached, a warning will be generated.
2478 minimum required amount has not been reached, a warning will be generated.
24722479 EOT
24732480 )
24742481 example('Limits-1', '4')
25052512 doc('monthlymin', <<'EOT'
25062513 Minimum required effort for any calendar month. This value cannot be
25072514 guaranteed by the scheduler. It is only checked after the schedule is
2508 complete. In case the minium required amount has not been reached, a warning
2515 complete. In case the minimum required amount has not been reached, a warning
25092516 will be generated.
25102517 EOT
25112518 )
25242531 doc('weeklymin', <<'EOT'
25252532 Minimum required effort for any calendar week. This value cannot be guaranteed by
25262533 the scheduler. It is only checked after the schedule is complete. In case the
2527 minium required amount has not been reached, a warning will be generated.
2534 minimum required amount has not been reached, a warning will be generated.
25282535 EOT
25292536 )
25302537 end
26312638 A logical expression is a combination of operands and mathematical operations.
26322639 The final result of a logical expression is always true or false. Logical
26332640 expressions are used the reduce the properties in a report to a certain subset
2634 or to select alternatives for the cell content of a table. When used with
2635 attributes like [[hidetask]] or [[hideresource]] the logical expression
2641 or to select alternatives for the cell content of a table. When the
2642 logical expression is used with attributes like [[hidetask]] or [[hideresource]] and
26362643 evaluates to true for a certain property, this property is hidden or rolled-up
26372644 in the report.
26382645
26542661 the validity first. E. g. to compare the end date of the ''''plan''''
26552662 scenario with the ''''maxend'''' value use ''''isvalid(plan.maxend) &
26562663 (plan.end > plan.maxend)''''. The ''''&'''' and ''''|'''' operators are lazy.
2657 If the result is already known after evaluation the first operand, the second
2664 If the result is already known after evaluation of the first operand, the second
26582665 operand will not be evaluated any more.
26592666 EOT
26602667 )
26892696 will expand to ''''This stupid text'''' if called as ''''${FOO "stupid"}''''.
26902697 Macros may call other macros. All macro arguments must be enclosed by double
26912698 quotes. In case the argument contains a double quote, it must be escaped by a
2692 slash (''''/'''').
2693
2694 User defined macro IDs must have at least one uppercase letter as all
2699 backslash (''''\'''').
2700
2701 User defined macro IDs should start with one uppercase letter as all
26952702 lowercase letter IDs are reserved for built-in macros.
26962703
26972704 To terminate the macro definition, the ''''<nowiki>]</nowiki>'''' must be the
30173024 of list attributes is not recommended. User defined attributes are available
30183025 as well.
30193026
3020 An operand can be a negated operand by prefixing a ~ charater or it can be
3027 An operand can be a negated operand by prefixing a ~ character or it can be
30213028 another logical expression enclosed in braces.
30223029 EOT
30233030 )
30363043 [ @val[0], @val[1] ]
30373044 })
30383045 arg(1, 'operand', <<'EOT'
3039 An operand can consist of a date, a text string or a numerical value. It can also be the name of a declared flag. Finally, an operand can be a negated operand by prefixing a ~ charater or it can be another operation enclosed in braces.
3046 An operand can consist of a date, a text string or a numerical value. It can also be the name of a declared flag. Finally, an operand can be a negated operand by prefixing a ~ character or it can be another operation enclosed in braces.
30403047 EOT
30413048 )
30423049 end
30743081 })
30753082 arg(0, 'id', <<"EOT"
30763083 An optional ID. If you ever want to reference this property, you must specify
3077 your own unique ID. If no ID is specified one will be automatically generated.
3084 your own unique ID. If no ID is specified, one will be automatically generated.
30783085 These IDs may become visible in reports, but may change at any time. You may
30793086 never rely on automatically generated IDs.
30803087 EOT
31393146 pattern(%w( _niku ), lambda {
31403147 :niku
31413148 })
3142 descr('Generate a XOG XML file to be used with Clarity.')
3149 descr('Generate an XOG XML file to be used with Clarity.')
31433150 end
31443151
31453152 def rule_outputFormats
32373244 doc('extend', <<'EOT'
32383245 Often it is desirable to collect more information in the project file than is
32393246 necessary for task scheduling and resource allocation. To add such information
3240 to tasks, resources or accounts the user can extend these properties with
3247 to tasks, resources or accounts, the user can extend these properties with
32413248 user-defined attributes. The new attributes can be of various types such as
32423249 text, date or reference to capture various types of data. Optionally the user
32433250 can specify if the attribute value should be inherited from the enclosing
32663273 arg(1, 'date', 'Alternative date to be used as current date for all ' +
32673274 'computations')
32683275
3276 pattern(%w( _markdate !date ), lambda {
3277 @project['markdate'] = @val[1]
3278 @scanner.addMacro(TextParser::Macro.new('markdate', @val[1].to_s,
3279 @sourceFileInfo[0]))
3280 @scanner.addMacro(TextParser::Macro.new(
3281 'today', @val[1].to_s(@project['timeFormat']), @sourceFileInfo[0]))
3282 })
3283 doc('markdate', <<'EOT'
3284 Specify the reference date that TaskJuggler uses as date that can be specified
3285 and set by the user. It can be used as additional point in time to help with
3286 tracking tasks. If no value is specified, the current value of the system clock is used.
3287 EOT
3288 )
3289 arg(1, 'date', 'Alternative date to be used as custom date specified by the user')
3290
32693291 pattern(%w( !numberFormat ), lambda {
32703292 @project['numberFormat'] = @val[0]
32713293 })
32843306 })
32853307 doc('outputdir',
32863308 'Specifies the directory into which the reports should be generated. ' +
3287 'This will not affect reports whos name start with a slash. This ' +
3288 'setting can be overwritten by the command line option.')
3309 'This will not affect reports whose name start with a slash. This ' +
3310 'setting can be overwritten by the command line option -o or --output-dir.')
32893311 arg(1, 'directory', 'Path to an existing directory')
32903312
32913313 pattern(%w( !scenario ))
32933315 @project['shortTimeFormat'] = @val[1]
32943316 })
32953317 doc('shorttimeformat',
3296 'Specifies time format for time short specifications. This is normal' +
3297 'just the hour and minutes.')
3318 'Specifies time format for short time specifications. This is normal ' +
3319 'just hours and minutes.')
32983320 arg(1, 'format', 'strftime like format string')
32993321
33003322 pattern(%w( !timeformat ), lambda {
33513373 tracking scenario and may not have any bookings of their own. The tracking
33523374 scenario must also be specified to use time and status sheet reports.
33533375
3354 The tracking scenario must be defined after all scenario have been defined.
3376 The tracking scenario must be defined after all scenarios have been defined.
33553377
33563378 The tracking scenario and all scenarios derived from it will be scheduled in
33573379 projection mode. This means that the scheduler will only add bookings after
34713493 # documentation.
34723494 pattern(%w( !projectPropertiesBody ))
34733495 doc('properties', <<'EOT'
3474 The project properties. Every project must consists of at least one task. The other properties are optional. To save the scheduled data at least one output generating property should be used.
3496 The project properties. Every project must consist of at least one task. The other properties are optional. To save the scheduled data at least one output generating property should be used.
34753497 EOT
34763498 )
34773499 end
34883510 doc('include.project', <<'EOT'
34893511 Includes the specified file name as if its contents would be written
34903512 instead of the include property. When the included files contains other
3491 include statements or report definitions, the filenames are relative to file
3513 include statements or report definitions, the filenames are relative to the file
34923514 where they are defined in.
34933515
34943516 This version of the include directive may only be used inside the [[project]]
35053527 Includes the specified file name as if its contents would be written
35063528 instead of the include property. The only exception is the include
35073529 statement itself. When the included files contains other include
3508 statements or report definitions, the filenames are relative to file
3530 statements or report definitions, the filenames are relative to the file
35093531 where they are defined in.
35103532
35113533 The included file may only contain macro definitions. This version of the
36663688 Includes the specified file name as if its contents would be written
36673689 instead of the include property. The only exception is the include
36683690 statement itself. When the included files contains other include
3669 statements or report definitions, the filenames are relative to file
3691 statements or report definitions, the filenames are relative to the file
36703692 where they are defined in. include commands can be used in the project
36713693 header, at global scope or between property declarations of tasks,
36723694 resources, and accounts.
36883710 end
36893711 if attributeDefinition.scenarioSpecific
36903712 @scenarioIdx = 0 unless @val[1]
3691 attr = @property[attrId, 0]
36923713 else
36933714 if @val[1]
36943715 error('purge_non_sc_spec_attr',
36953716 'Scenario specified for a non-scenario specific attribute')
36963717 end
3697 attr = @property.get(attrId)
36983718 end
36993719 if @property.attributeDefinition(attrId).scenarioSpecific
37003720 @property.getAttribute(attrId, @scenarioIdx).reset
37783798 EOT
37793799 )
37803800
3801 singlePattern('_annualleavelist')
3802 descr(<<'EOT'
3803 A list with all annual leave intervals. The list can be customized with the
3804 [[listtype.column|listtype]] attribute.
3805 EOT
3806 )
3807
37813808 singlePattern('_alert')
37823809 descr(<<'EOT'
37833810 The alert level of the property that was reported with the date closest to the
38013828 singlePattern('_alerttrend')
38023829 descr(<<'EOT'
38033830 Shows how the alert level at the end of the report period compares to the
3804 alert level at the begining of the report period. Possible values are
3831 alert level at the beginning of the report period. Possible values are
38053832 ''''Up'''', ''''Down'''' or ''''Flat''''.
38063833 EOT
38073834 )
38383865 singlePattern('_closedtasks')
38393866 descr(<<'EOT'
38403867 The number of sub-tasks (including the current task) that have been closed
3841 during the reported time period. Closed means that they have and end date
3868 during the reported time period. Closed means that they have an end date
38423869 before the current time or [[now]] date.
38433870 EOT
38443871 )
38593886 singlePattern('_complete')
38603887 descr(<<'EOT'
38613888 The completion degree of a task. Unless a completion degree is manually
3862 provided, this is a computed value relative the [[now]] date of the project. A
3889 provided, this is a computed value relative to the [[now]] date of the project. A
38633890 task that has ended before the now date is always 100% complete. A task that
3864 starts at or after the now date is always 0%. For [[effort]] based task the
3891 starts at or after the now date is always 0%. For [[effort]] based tasks the
38653892 computation degree is the percentage of done effort of the overall effort. For
3866 other leaf task, the completion degree is the percentage of the already passed
3867 duration of the overall task duration. For container task, it's always the
3893 other leaf tasks, the completion degree is the percentage of the already passed
3894 duration of the overall task duration. For container tasks, it's always the
38683895 average of the direct sub tasks. If the sub tasks consist of a mixture of
38693896 effort and non-effort tasks, the completion value is only of limited value.
38703897 EOT
38783905 descr('Deprecated alias for complete')
38793906
38803907 singlePattern('_criticalness')
3881 descr('A measure for how much effort the resource is allocated for, or' +
3882 'how strained the allocated resources of a task are')
3908 descr('A measure for how much effort the resource is allocated for, or ' +
3909 'how strained the allocated resources of a task are.')
38833910
38843911 singlePattern('_cost')
38853912 descr(<<'EOT'
39313958 descr(<<'EOT'
39323959 A list of tasks that depend on the current task. The list contains the names,
39333960 the IDs, the date and the type of dependency. For the type the following
3934 symbols are used for <nowiki><dep></nowiki>.
3961 symbols are used for <nowiki><dep></nowiki>:
39353962
39363963 * '''<nowiki>]->[</nowiki>''': End-to-Start dependency
39373964 * '''<nowiki>[->[</nowiki>''': Start-to-Start dependency
39403967
39413968 The list can be customized by the [[listitem.column|listitem]] and
39423969 [[listtype.column]] attributes. The dependency symbol can be generated via
3943 the ''''dependency'''' attribute inthe query, the target date via the
3970 the ''''dependency'''' attribute in the query, the target date via the
39443971 ''''date'''' attribute.
39453972 EOT
39463973 )
40184045 singlePattern('_journal')
40194046 descr(<<'EOT'
40204047 The journal entries for the task or resource for the reported interval. The
4021 generated text can be customized with the [[journalmode]],
4048 generated text can be customized with [[journalmode]],
40224049 [[journalattributes]], [[hidejournalentry]] and [[sortjournalentries]]. If
40234050 used in queries without a property context, the journal for the complete
40244051 project is generated.
40794106 singlePattern('_opentasks')
40804107 descr(<<'EOT'
40814108 The number of sub-tasks (including the current task) that have not yet been
4082 closed during the reported time period. Closed means that they have and end
4109 closed during the reported time period. Closed means that they have an end
40834110 date before the current time or [[now]] date.
40844111 EOT
40854112 )
41014128
41024129 The list can be customized by the [[listitem.column|listitem]] and
41034130 [[listtype.column|listtype]] attributes. The dependency symbol can be
4104 generated via the ''''dependency'''' attribute inthe query, the target date
4131 generated via the ''''dependency'''' attribute in the query, the target date
41054132 via the ''''date'''' attribute.
41064133 EOT
41074134 )
43634390 })
43644391 doc('height', <<'EOT'
43654392 Set the height of the report in pixels. This attribute is only used for
4366 reports that cannot determine the height based on the content. Such report can
4393 reports that cannot determine the height based on the content. Such reports can
43674394 be freely resized to fit in. The vast majority of reports can determine their
43684395 height based on the provided content. These reports will simply ignore this
43694396 setting.
44204447 @property.set('rawHtmlHead', @val[1])
44214448 })
44224449 doc('rawhtmlhead', <<'EOT'
4423 Define a HTML fragment that will be inserted at the end of the HTML head
4450 Define an HTML fragment that will be inserted at the end of the HTML head
44244451 section.
44254452 EOT
44264453 )
44844511 doc('resourceroot', <<'EOT'
44854512 Only resources below the specified root-level resources are exported. The
44864513 exported resources will have the ID of the root-level resource stripped from
4487 their ID, so that the sub-resourcess of the root-level resource become
4514 their ID, so that the sub-resources of the root-level resource become
44884515 top-level resources in the report file.
44894516 EOT
44904517 )
45334560 })
45344561 doc('width', <<'EOT'
45354562 Set the width of the report in pixels. This attribute is only used for
4536 reports that cannot determine the width based on the content. Such report can
4563 reports that cannot determine the width based on the content. Such reports can
45374564 be freely resized to fit in. The vast majority of reports can determine their
45384565 width based on the provided content. These reports will simply ignore this
45394566 setting.
47954822 })
47964823 doc('resourcereport', <<'EOT'
47974824 The report lists resources and their respective values in a table. The task
4798 that are the resources are allocated to can be listed as well. To reduce the
4825 that the resources are allocated to can be listed as well. To reduce the
47994826 list of included resources, you can use the [[hideresource]],
4800 [[rollupresource]] or [[resourceroot]] attributes. The order of the task can
4827 [[rollupresource]] or [[resourceroot]] attributes. The order of the tasks can
48014828 be controlled with [[sortresources]]. If the first sorting criteria is tree
48024829 sorting, the parent resources will always be included to form the tree.
48034830 Tree sorting is the default. You need to change it if you do not want certain
48564883 efficiency of 5.0. Keep in mind that you cannot track the members of the team
48574884 individually if you use this feature. They always act as a group.
48584885
4859 The other use is to model performance variations between your resources. Again, this is a fairly crude mechanism and should be used with care. A resource that isn't every good at some task might be pretty good at another. This can't be taken into account as the resource efficiency can only set globally for all tasks.
4886 The other use is to model performance variations between your resources. Again, this is a fairly crude mechanism and should be used with care. A resource that isn't very good at some task might be pretty good at another. This can't be taken into account as the resource efficiency can only be set globally for all tasks.
48604887
48614888 All resources that do not contribute effort to the task, should have an
48624889 efficiency of 0.0. A typical example would be a conference room. It's necessary for a meeting, but it does not contribute any work.
48734900 pattern(%w( _booking !resourceBooking ))
48744901 doc('booking.resource', <<'EOT'
48754902 The booking attribute can be used to report actually completed work. A task
4876 with bookings must be [[scheduling|scheduled]] in ''''asap'''' mode. If the
4903 with bookings must be [[scheduling|scheduled]] in ''''ASAP'''' mode. If the
48774904 scenario is not the [[trackingscenario|tracking scenario]] or derived from it,
48784905 the scheduler will not allocate resources prior to the current date or the
48794906 date specified with [[now]] when a task has at least one booking.
49594986 @shiftAssignments = nil
49604987 })
49614988 level(:deprecated)
4962 also('shift.resource')
4989 also('shifts.resource')
49634990 doc('shift.resource', <<'EOT'
49644991 This keyword has been deprecated. Please use [[shifts.resource|shifts
49654992 (resource)]] instead.
50695096 scenarios. A nested scenario uses all attributes from the enclosing scenario
50705097 unless the user has specified a different value for this attribute.
50715098
5072 By default, the scheduler assigns resources to task beginning with the project
5099 By default, the scheduler assigns resources to tasks beginning with the project
50735100 start date. If the scenario is switched to projection mode, no assignments
50745101 will be made prior to the current date or the date specified by [[now]]. In
5075 this case, TaskJuggler assumes, that all assignements prior to the
5102 this case, TaskJuggler assumes, that all assignments prior to the
50765103 current date have been provided by [[booking.task]] statements.
50775104 EOT
50785105 )
50875114 })
50885115 doc('active', <<'EOT'
50895116 Enable the scenario to be scheduled or not. By default, all scenarios will be
5090 scheduled. If a scenario is marked as inactive, it not be scheduled and will
5117 scheduled. If a scenario is marked as inactive, it cannot be scheduled and will
50915118 be ignored in the reports.
50925119 EOT
50935120 )
57025729 @property = @propertyStack.pop
57035730 })
57045731 doc('task.statussheet', <<'EOT'
5705 Opens the task with the specified ID to add a status report. Child task can be
5732 Opens the task with the specified ID to add a status report. Child tasks can be
57065733 opened inside this context by specifying their relative ID to this parent.
57075734 EOT
57085735 )
60426069 )
60436070
60446071 singlePattern('$ID')
6045 arg(0, 'ID', 'Just the ID of the task without and parent IDs.')
6072 arg(0, 'ID', 'Just the ID of the task without any parent IDs.')
60466073
60476074 pattern(%w( !relativeId ), lambda {
60486075 task = @property
61586185 doc('taskreport', <<'EOT'
61596186 The report lists tasks and their respective values in a table. To reduce the
61606187 list of included tasks, you can use the [[hidetask]], [[rolluptask]] or
6161 [[taskroot]] attributes. The order of the task can be controlled with
6188 [[taskroot]] attributes. The order of the tasks can be controlled with
61626189 [[sorttasks]]. If the first sorting criteria is tree sorting, the parent tasks
61636190 will always be included to form the tree. Tree sorting is the default. You
61646191 need to change it if you do not want certain parent tasks to be included in
62176244 pattern(%w( _booking !taskBooking ))
62186245 doc('booking.task', <<'EOT'
62196246 The booking attribute can be used to report actually completed work. A task
6220 with bookings must be [[scheduling|scheduled]] in ''''asap'''' mode. If the
6247 with bookings must be [[scheduling|scheduled]] in ''''ASAP'''' mode. If the
62216248 scenario is not the [[trackingscenario|tracking scenario]] or derived from it,
62226249 the scheduler will not allocate resources prior to the current date or the
62236250 date specified with [[now]] when a task has at least one booking.
63206347 finished.
63216348
63226349 By using the 'depends' attribute, the scheduling policy is automatically set
6323 to asap. If both depends and precedes are used, the last policy counts.
6350 to ASAP. If both depends and precedes are used, the last policy counts.
63246351 EOT
63256352 )
63266353 example('Depends1')
64176444 The end attribute provides a guideline to the scheduler when the task should
64186445 end. It will never end later, but it may end earlier when allocated
64196446 resources are not available that long. When an end date is provided for a
6420 container task, it will be passed down to ALAP task that don't have a well
6447 container task, it will be passed down to ALAP tasks that don't have a well
64216448 defined end criteria.
64226449
6423 Setting an end date will implicitely set the scheduling policy for this task
6450 Setting an end date will implicitly set the scheduling policy for this task
64246451 to ALAP.
64256452 EOT
64266453 )
64336460 level(:deprecated)
64346461 doc('endcredit', <<'EOT'
64356462 Specifies an amount that is credited to the accounts specified by the
6436 [[chargeset]] attributes at the moment the tasks ends.
6463 [[chargeset]] attributes at the moment the task ends.
64376464 EOT
64386465 )
64396466 also('charge')
64656492 For the length calculation, the global working hours and the global leaves
64666493 matter unless the task has [[shifts.task|shifts]] assigned. In the latter case
64676494 the working hours and leaves of the shift apply for the specified period to
6468 determine if a slot is working time or not. If a resource has additinal
6495 determine if a slot is working time or not. If a resource has additional
64696496 working hours defined, it's quite possible that a task with a length of 5d
64706497 will have an allocated effort larger than 40 hours. Resource working hours
64716498 only have an impact on whether an allocation is made or not for a particular
65136540 })
65146541 doc('milestone', <<'EOT'
65156542 Turns the task into a special task that has no duration. You may not specify a
6516 duration, length, effort or subtasks for a milestone task.
6543 duration, length, effort or subtask for a milestone task.
65176544
65186545 A task that only has a start or an end specification and no duration
65196546 specification, inherited start or end dates, no dependencies or sub tasks,
65506577 level(:deprecated)
65516578 doc('startcredit', <<'EOT'
65526579 Specifies an amount that is credited to the account specified by the
6553 [[chargeset]] attributes at the moment the tasks starts.
6580 [[chargeset]] attributes at the moment the task starts.
65546581 EOT
65556582 )
65566583 also('charge')
65656592 end
65666593 })
65676594 doc('precedes', <<'EOT'
6568 Specifies that the tasks with the specified IDs cannot start before the task
6595 Specifies that the tasks with the specified IDs cannot start before this task
65696596 has been finished. If multiple IDs are specified, they must be separated by
65706597 commas. IDs must be either global or relative. A relative ID starts with a
65716598 number of '!'. Each '!' moves the scope to the parent task. Global IDs do not
65726599 contain '!', but have IDs separated by dots.
65736600
65746601 By using the 'precedes' attribute, the scheduling policy is automatically set
6575 to alap. If both depends and precedes are used within a task, the last policy
6602 to ALAP. If both depends and precedes are used within a task, the last policy
65766603 counts.
65776604 EOT
65786605 )
65886615 Specifies the priority of the task. A task with higher priority is more
65896616 likely to get the requested resources. The default priority value of all tasks
65906617 is 500. Don't confuse the priority of a tasks with the importance or urgency
6591 of a task. It only increases the chances that the tasks gets the requested
6618 of a task. It only increases the chances that the task gets the requested
65926619 resources. It does not mean that the task happens earlier, though that is
65936620 usually the effect you will see. It also does not have any effect on tasks
65946621 that don't have any resources assigned (e.g. milestones).
65956622
6596 For milestones it will raise or lower the chances that task leading up the
6597 milestone will get their resources over task with equal priority that compete
6623 For milestones, it will raise or lower the chances that tasks leading up the
6624 milestone will get their resources over tasks with equal priority that compete
65986625 for the same resources.
65996626
66006627 This attribute is inherited by subtasks if specified prior to the definition
66126639 begin
66136640 @property['projectid', @scenarioIdx] = @val[1]
66146641 rescue AttributeOverwrite
6615 # This attribute always overwrites the implicitely provided ID.
6642 # This attribute always overwrites the implicitly provided ID.
66166643 end
66176644 })
66186645 doc('projectid.task', <<'EOT'
6619 In larger projects it may be desireable to work with different project IDs for
6620 parts of the project. This attribute assignes a new project ID to this task an
6646 In larger projects it may be desirable to work with different project IDs for
6647 parts of the project. This attribute assignes a new project ID to this task and
66216648 all subsequently defined sub tasks. The project ID needs to be declared first using [[projectid]] or [[projectids]].
66226649 EOT
66236650 )
66616688 })
66626689 doc('scheduling', <<'EOT'
66636690 Specifies the scheduling policy for the task. A task can be scheduled from
6664 start to end (As Soon As Possible, asap) or from end to start (As Late As
6665 Possible, alap).
6691 start to end (As Soon As Possible, ASAP) or from end to start (As Late As
6692 Possible, ALAP).
66666693
66676694 A task can be scheduled from start to end (ASAP mode) when it has a hard
66686695 (start) or soft (depends) criteria for the start time. A task can be scheduled
66716698
66726699 Some task attributes set the scheduling policy implicitly. This attribute can
66736700 be used to explicitly set the scheduling policy of the task to a certain
6674 direction. To avoid it being overwritten again by an implicit attribute this
6701 direction. To avoid it being overwritten again by an implicit attribute, this
66756702 attribute should always be the last attribute of the task.
66766703
66776704 A random mixture of ASAP and ALAP tasks can have unexpected side effects on
66786705 the scheduling of the project. It increases significantly the scheduling
66796706 complexity and results in much longer scheduling times. Especially in projects
6680 with many hundreds of tasks the scheduling time of a project with a mixture of
6681 ASAP and ALAP times can be 2 to 10 times longer. When the projects contains
6682 chains of ALAP and ASAP tasks the tasks further down the dependency chain will
6683 be served much later than other non-chained task even when they have a much
6707 with many hundreds of tasks, the scheduling time of a project with a mixture of
6708 ASAP and ALAP times can be 2 to 10 times longer. When the project contains
6709 chains of ALAP and ASAP tasks, the tasks further down the dependency chain will
6710 be served much later than other non-chained tasks, even when they have a much
66846711 higher priority. This can result in situations where high priority tasks do
6685 not get their resources even though the parallel competing tasks have a much
6712 not get their resources, even though the parallel competing tasks have a much
66866713 lower priority.
66876714
6688 ALAP tasks may not have [[booking.task|bookings]] since the first booked slot
6715 ALAP tasks may not have [[booking.task|bookings]], since the first booked slot
66896716 determines the start date of the task and prevents it from being scheduled
66906717 from end to start.
66916718
67446771 Limits the working time for this task during the specified interval
67456772 to the working hours of the given shift. Multiple shifts can be defined, but
67466773 shift intervals may not overlap. This is an additional working time
6747 restriction ontop of the working hours of the allocated resources. It does not
6774 restriction on top of the working hours of the allocated resources. It does not
67486775 replace the resource working hour restrictions. For a resource to be assigned
67496776 to a time slot, both the respective task shift as well as the resource working
67506777 hours must declare the time slot as duty slot.
67626789 The start attribute provides a guideline to the scheduler when the task should
67636790 start. It will never start earlier, but it may start later when allocated
67646791 resources are not available immediately. When a start date is provided for a
6765 container task, it will be passed down to ASAP task that don't have a well
6792 container task, it will be passed down to ASAP tasks that don't have a well
67666793 defined start criteria.
67676794
6768 Setting a start date will implicitely set the scheduling policy for this task
6795 Setting a start date will implicitly set the scheduling policy for this task
67696796 to ASAP.
67706797 EOT
67716798 )
67936820 @property = @property.parent
67946821 })
67956822 doc('textreport', <<'EOT'
6796 This report consists of 5 RichText sections, a header, a center section with a
6823 This report consists of 5 [[Rich_Text_Attributes|Rich Text]] sections, a header, a center section with a
67976824 left and right margin and a footer. The sections may contain the output of
67986825 other defined reports.
67996826 EOT
68186845 arg(1, 'format', <<'EOT'
68196846 Ordinary characters placed in the format string are copied without
68206847 conversion. Conversion specifiers are introduced by a `%' character, and are
6821 replaced in s as follows:
6848 replaced as follows:
68226849
68236850 * ''''%a'''' The abbreviated weekday name according to the current locale.
68246851
69787005
69797006 The intended use for time sheets is to have all resources report a time sheet
69807007 every day, week or month. All time sheets can be added to the project plan.
6981 The status information is always used to determin the current status of the
7008 The status information is always used to determine the current status of the
69827009 project. The [[work]], [[remaining]] and [[end.timesheet|end]] attributes are
69837010 ignored if there are also [[booking.task|bookings]] for the resource in the
69847011 time sheet period. The non-ignored attributes of the time sheets will be
70137040 })
70147041 doc('newtask', <<'EOT'
70157042 The keyword can be used to request a new task to the project. If the task ID
7016 requires further parent task that don't exist yet, these tasks will be
7043 requires further parent tasks that don't exist yet, these tasks will be
70177044 requested as well. If the task exists already, an error will be generated. The
70187045 newly requested task can be used immediately to report progress and status
70197046 against it. These tasks will not automatically be added to the project plan.
71477174 that are not hidden by [[hideaccount]], [[hideresource]] and [[hidetask]]. By
71487175 default, all properties are excluded. You must provide at least one of the
71497176 ''''hide...'''' attributes to select the properties you want to have included
7150 in the report. Please be aware that total number of columns is the product of
7177 in the report. Please be aware that the total number of columns is the product of
71517178 attributes defined with [[columns]] times the number of included properties.
7152 Select you values carefully or you will end up with very large reports.
7179 Select your values carefully or you will end up with very large reports.
71537180
71547181 The column headers can be customized by using the [[title.column|title]]
71557182 attribute. When you include multiple properties, these headers are not unique
7156 unless you include mini-queries to modify them based on the property they
7157 colum is represeting. You can use the queries
7183 unless you include mini-queries to modify them based on the property the
7184 column is representing. You can use the queries
71587185 ''''<nowiki><-id-></nowiki>'''', ''''<nowiki><-name-></nowiki>'''',
71597186 ''''<nowiki><-scenario-></nowiki>'''' and
71607187 ''''<nowiki><-attribute-></nowiki>''''. ''''<nowiki><-id-></nowiki>'''' is
71697196 all kinds of values that are being tracked. Report formats that don't support
71707197 a mix of different values will just show the values of the second column.
71717198
7172 The values in the CSV files are fixed units and cannot be formated. Effort
7199 The values in the CSV files are fixed units and cannot be formatted. Effort
71737200 values are always in resource-days. This allows other software to interpret
71747201 the file without any need for additional context information.
71757202
71767203 The HTML version generates SVG graphs that are embedded in the HTML page.
7177 These graphs are only visble if the web browser supports HTML5. This is true
7204 These graphs are only visible if the web browser supports HTML5. This is true
71787205 for the latest generation of browsers, but older browsers may not support this
71797206 format.
71807207 EOT
71867213 pattern(%w( _tracereport !optionalID !reportName ), lambda {
71877214 newReport(@val[1], @val[2], :tracereport, @sourceFileInfo[0]) do
71887215 # The top-level always inherits the global timeFormat setting. This is
7189 # not desireable in this case, so we ignore this.
7216 # not desirable in this case, so we ignore this.
71907217 if (@property.level == 0 && !@property.provided('timeFormat')) ||
71917218 (@property.level > 0 && !@property.modified?('timeFormat'))
71927219 # CSV readers such of Libre-/OpenOffice can't deal with time zones. We
73697396 })
73707397 doc('end.timesheet', <<'EOT'
73717398 The expected end date for the task. This can only be used for duration based
7372 task. For effort based task [[remaining]] has to be used.
7399 tasks. For effort based tasks [[remaining]] has to be used.
73737400 EOT
73747401 )
73757402 example('TimeSheet1', '5')
73857412 })
73867413 doc('priority.timesheet', <<'EOT'
73877414 The priority is a value between 1 and 1000. It is used to determine the
7388 sequence of task when converting [[work]] to [[booking.task|bookings]]. Tasks
7415 sequence of tasks when converting [[work]] to [[booking.task|bookings]]. Tasks
73897416 that need to finish earlier in the period should have a high priority, tasks
73907417 that end later in the period should have a low priority. For tasks that don't
73917418 get finished in the reported period the priority should be set to 1.
73997426 The remaining effort for the task. This value is ignored if there are
74007427 [[booking.task|bookings]] for the resource that overlap with the time sheet
74017428 period. If there are no bookings, the value is compared with the [[effort]]
7402 specification of the task. If there a mismatch between the accumulated effort
7429 specification of the task. If there is a mismatch between the accumulated effort
74037430 specified with bookings, [[work]] and [[remaining]] on one side and the
74047431 specified [[effort]] on the other, a warning is generated.
74057432
74157442 @timeSheetRecord.work = @val[1]
74167443 })
74177444 doc('work', <<'EOT'
7418 The amount of time that the resource has spend with the task during the
7445 The amount of time that the resource has spent with the task during the
74197446 reported period. This value is ignored when there are
74207447 [[booking.task|bookings]] for the resource overlapping with the time sheet
74217448 period. If there are no bookings, TaskJuggler will try to convert the work
75517578 midnight that day. So the day of the end date is not included in the interval!
75527579 The start and end dates must be separated by a hyphen character.
75537580
7554 In the second form specifies the start date and an interval duration. The
7581 The second form specifies the start date and an interval duration. The
75557582 duration must be prefixed by a plus character.
75567583 EOT
75577584 )
75717598 doc('warn', <<'EOT'
75727599 The warn attribute adds a [[logicalexpression|logical expression]] to the
75737600 property. The condition described by the logical expression is checked after
7574 the scheduling and an warning is generated if the condition evaluates to true.
7601 the scheduling and a warning is generated if the condition evaluates to true.
75757602 This attribute is primarily intended for testing purposes.
75767603 EOT
75777604 )
77077734 pattern(%w( !workinghours ))
77087735 doc('workinghours.project', <<'EOT'
77097736 Set the default working hours for all subsequent resource definitions. The
7710 standard working hours are 9:00am - 12:00am, 1:00pm - 18:00pm, Monday to
7737 standard working hours are 9:00am - 12:00am, 1:00pm - 6:00pm, Monday to
77117738 Friday. The working hours specification limits the availability of resources
77127739 to certain time slots of week days.
77137740
1717 # This is an extension and modification of the standard String class. We do a
1818 # lot of UTF-8 character processing in the parser. Ruby 1.8 does not have good
1919 # enough UTF-8 support and Ruby 1.9 only handles UTF-8 characters as Strings.
20 # This is very inefficient compared to representing them as Fixnum objects.
20 # This is very inefficient compared to representing them as Integer objects.
2121 # Some of these hacks can be removed once we have switched to 1.9 support
2222 # only.
2323 class String
5757 alias old_double_left_angle <<
5858
5959 # Replacement for the existing << operator that also works for characters
60 # above Fixnum 255 (UTF-8 characters).
61 def << (obj)
60 # above Integer 255 (UTF-8 characters).
61 def <<(obj)
6262 if obj.is_a?(String) || (obj < 256)
6363 # In this case we can use the built-in concat.
6464 concat(obj)
1616 class TaskJuggler
1717
1818 # Class to store the working hours for each day of the week. The working hours
19 # are stored as Arrays of Fixnum intervals for each day of the week. A day off
19 # are stored as Arrays of Integer intervals for each day of the week. A day off
2020 # is modelled as empty Array for that week day. The start end end times of
2121 # each working period are stored as seconds after midnight.
2222 class WorkingHours
9999
100100 # Set the working hours for a given week day. +dayOfWeek+ must be 0 for
101101 # Sunday, 1 for Monday and so on. +intervals+ must be an Array that
102 # contains an Array with 2 Fixnums for each working period. Each value
102 # contains an Array with 2 Integers for each working period. Each value
103103 # specifies the time of day as minutes after midnight. The first value is
104104 # the start time of the interval, the second the end time.
105105 def setWorkingHours(dayOfWeek, intervals)
132132
133133 # Return the working hour intervals for a given day of the week.
134134 # +dayOfWeek+ must 0 for Sunday, 1 for Monday and so on. The result is an
135 # Array that contains Arrays of 2 Fixnums.
135 # Array that contains Arrays of 2 Integers.
136136 def getWorkingHours(dayOfWeek)
137137 @days[dayOfWeek]
138138 end
203203 end
204204
205205 def to_s(indent)
206 '<!-- ' + @text + " -->\n#{' ' * indent}"
206 '<!-- ' + canonicalize_comment(@text) + " -->\n#{' ' * indent}"
207 end
208
209 private
210
211 # It is crucial to canonicalize xml comment text because xml
212 # comment syntax forbids having a -- in the comment body. I
213 # picked emacs's "M-x comment-region" approach of putting a
214 # backslash between the two.
215 def canonicalize_comment(text)
216 new_text = text.gsub("--", "-\\-")
217 new_text
207218 end
208219
209220 end
6767
6868 def processArguments(argv)
6969 super do
70 @opts.banner += <<'EOT'
70 @opts.banner.prepend(<<'EOT'
7171 This is the main application. It reads in your project files, schedules the
7272 project and generates the reports.
73
7374 EOT
75 )
7476 @opts.on('--debuglevel N', Integer,
7577 format("Verbosity of debug output")) do |arg|
7678 TaskJuggler::Log.level = arg
9999
100100 def processArguments(argv)
101101 super do
102 @opts.banner += <<'EOT'
102 prebanner = <<'EOT'
103103 The TaskJuggler client is used to send commands and data to the TaskJuggler
104104 daemon. The communication is done via TCP/IP.
105105
124124 end
125125 end
126126 args = args.join(' ')
127 @opts.banner += " #{cmd[:label] + ' ' + args + tail}" +
127 prebanner += " #{cmd[:label] + ' ' + args + tail}" +
128128 "\n\n#{' ' * 10 + format(cmd[:descr], 10)}\n"
129129 end
130 @opts.banner.prepend(prebanner)
130131 @opts.on('-p', '--port <NUMBER>', Integer,
131132 format('Use the specified TCP/IP port')) do |arg|
132133 @port = arg
4141
4242 def processArguments(argv)
4343 super do
44 @opts.banner += <<'EOT'
44 @opts.banner.prepend(<<'EOT'
4545 The TaskJuggler daemon can be used to quickly generate reports for a number
4646 of scheduled projects that are resident in memory. Once the daemon has been
4747 started tj3client can be used to control it.
48
4849 EOT
50 )
4951 @opts.on('-d', '--dont-daemonize',
5052 format("Don't put program into daemon mode. Keep it " +
5153 'connected to the terminal and show debug output.')) do
3535
3636 def processArguments(argv)
3737 super do
38 @opts.banner += <<'EOT'
38 @opts.banner.prepend(<<'EOT'
3939 This program can be used to generate the user manual in HTML format or to get
4040 a textual help for individual keywords.
41
4142 EOT
43 )
4244 @opts.on('-d', '--dir <directory>', String,
4345 format('directory to put the manual')) do |dir|
4446 @directory = dir
4547 end
4648 @opts.on('--html',
4749 format('Show the user manual in your local web browser. ' +
48 'By default, Firefox is used or the brower specified ' +
50 'By default, Firefox is used or the browser specified ' +
4951 'with the $BROWSER environment variable.')) do
5052 @showHtml = true
5153 end
2626
2727 def processArguments(argv)
2828 super do
29 @opts.banner += <<'EOT'
29 @opts.banner.prepend(<<'EOT'
3030 This program can be used to receive filled-out status sheets via email.
3131 It reads the emails from STDIN and extracts the status sheet from the
3232 attached files. The status sheet is checked for correctness. Good status
3333 sheets are filed away. The sender be informed by email that the status
3434 sheets was accepted or rejected.
35
3536 EOT
37 )
3638 end
3739 end
3840
3737
3838 def processArguments(argv)
3939 super do
40 @opts.banner += <<'EOT'
40 @opts.banner.prepend(<<'EOT'
4141 This program can be used to out status sheets templates via email. It will
4242 generate status sheet templates for managers of the project. The project data
4343 will be accesses via tj3client from a running TaskJuggler server process.
44
4445 EOT
46 )
4547 @opts.on('-r', '--resource <ID>', String,
4648 format('Only generate template for given resource')) do |arg|
4749 @resourceList << arg
2929
3030 def processArguments(argv)
3131 super do
32 @opts.banner += <<'EOT'
32 @opts.banner.prepend(<<'EOT'
3333 This program can be used to receive filled-out time sheets via email. It
3434 reads the emails from STDIN and extracts the time sheet from the attached
3535 files. The time sheet is checked for correctness. Good time sheets are filed
3636 away. The sender will be informed by email that the time sheets was accepted
3737 or rejected.
38
3839 EOT
40 )
3941 end
4042 end
4143
3636
3737 def processArguments(argv)
3838 super do
39 @opts.banner += <<'EOT'
39 @opts.banner.prepend(<<'EOT'
4040 This program can be used to send out time sheets templates via email. It will
4141 generate time sheet templates for all resources of the project. The project
4242 data will be accesses via tj3client from a running TaskJuggler server process.
43
4344 EOT
45 )
4446 @opts.on('-r', '--resource <ID>', String,
4547 format('Only generate template for given resource')) do |arg|
4648 @resourceList << arg
3535
3636 def processArguments(argv)
3737 super do
38 @opts.banner += <<'EOT'
38 @opts.banner.prepend(<<'EOT'
3939 This program can be used to send out individual copies and a summary of all
4040 accepted time sheets a list of email addresses. The directory structures for
4141 templates and submitted time sheets must be present. The project data will be
4242 accesses via tj3client from a running TaskJuggler server process.
43
4344 EOT
45 )
4446 @opts.on('-r', '--resource <ID>', String,
4547 format('Only generate summary for given resource')) do |arg|
4648 @resourceList << arg
3939
4040 def processArguments(argv)
4141 super do
42 @opts.banner += <<'EOT'
42 @opts.banner.prepend(<<'EOT'
4343 The TaskJuggler web server can be used to serve the HTTP reports of
4444 TaskJuggler projects to be viewed by any HTML5 compliant web browser. It uses
4545 the TaskJuggler daemon (tj3d) for data hosting and report generation.
46
4647 EOT
48 )
4749 @opts.on('-d', '--dont-daemonize',
4850 format("Don't put program into daemon mode. Keep it " +
4951 'connected to the terminal and show debug output.')) do
3636 # We can't clone frozen objects. So just return a reference to them.
3737 # Built-in classed can't be cloned either. The check below is probably
3838 # cheaper than the frequent (hiddent) exceptions from those objects.
39 return self if frozen? || nil? || is_a?(Fixnum) || is_a?(Float) ||
39 return self if frozen? || nil? || is_a?(Integer) || is_a?(Float) ||
4040 is_a?(TrueClass) || is_a?(FalseClass) || is_a?(Symbol)
4141
4242 # In case we have loops in our graph, we return references, not
156156 end
157157 when :fieldEnd
158158 # We've completed processing a field. Add the field to the list of
159 # fields. Convert Fixnums and Floats in native types.
159 # fields. Convert Integers and Floats in native types.
160160 fields << unMarshal(field, quoted)
161161
162162 if c == "\n"
197197 if str.nil?
198198 nil
199199 elsif /^[-+]?\d+$/ =~ str
200 # field is a Fixnum
200 # field is an Integer
201201 str.to_i
202202 elsif /^[-+]?\d*\.?\d+([eE][-+]?\d+)?$/ =~ str
203203 # field is a Float
215215 def marshal(field)
216216 if field.nil?
217217 ''
218 elsif field.is_a?(Fixnum) || field.is_a?(Float) || field.is_a?(Bignum)
218 elsif field.is_a?(Integer) || field.is_a?(Float)
219219 # Numbers don't have to be quoted.
220220 field.to_s
221221 else
162162
163163 @yMinDate = cell if @yMinDate.nil? || cell < @yMinDate
164164 @yMaxDate = cell if @yMaxDate.nil? || cell > @yMaxDate
165 elsif cell.is_a?(Fixnum) || cell.is_a?(Float)
165 elsif cell.is_a?(Integer) || cell.is_a?(Float)
166166 if @dataType && @dataType != :number
167167 error("Column #{colIdx} contains non-number (#{cell}). " +
168168 "The columns will be ignored.")
3434 include HTMLGraphics
3535
3636 attr_reader :start, :end, :now, :weekStartsMonday, :header, :width,
37 :scale, :scales, :table
37 :scale, :scales, :table, :markdate
3838 attr_writer :viewWidth
3939
4040 # Create the GanttChart object, but don't do much right now. We still need
4242 # is the date that should be used as current date. _weekStartsMonday_ is
4343 # true if the weeks should start on Mondays instead of Sundays. _table_ is a
4444 # reference to the TableReport that the chart is part of.
45 def initialize(now, weekStartsMonday, columnDef, table = nil)
45 def initialize(now, weekStartsMonday, columnDef, table = nil, markdate = nil)
4646 # The start and end dates of the reported interval.
4747 @start = nil
4848 @end = nil
4949 @now = now
5050 @columnDef = columnDef
5151 @table = table
52 @markdate = markdate
5253
5354 # This defines the possible horizontal scales that the Gantt chart can
5455 # have. The scales differ in their resolution and the amount of detail
255256 # Also protect the current date line from other vertical lines.
256257 @router.addZone(@header.nowLineX - 1, 0, 3, @height - 1, false, true)
257258
259 # Protect the date set in custom reference line from other vertical lines.
260 if @header.markdateLineX
261 @router.addZone(@header.markdateLineX - 1, 0, 3, @height - 1, false, true)
262 end
263
258264 # Generate the dependency arrows for all visible tasks.
259265 @tasks.each do |task, lines|
260266 generateDepLines(task, lines)
2020 # holds the small scale (e. g. week or day).
2121 class GanttHeader
2222
23 attr_reader :gridLines, :nowLineX, :cellStartDates
23 attr_reader :gridLines, :nowLineX, :cellStartDates, :markdateLineX
2424 attr_accessor :height
2525
2626 # Create a GanttHeader object and generate the scales for the header.
3737
3838 # X coordinate of the "now" line. nil if "now" is off-chart.
3939 @nowLineX = nil
40
41 # X coordinate of the custom "markdate" line with date specified by user.
42 # nil if "markdate" is off-chart.
43 @markdateLineX = nil
4044
4145 # The x coordinates and width of the cells created by the small scale. The
4246 # values are stored as [ x, w ].
102106
103107 nlx = @chart.dateToX(@chart.now)
104108 @nowLineX = nlx if nlx
109
110 if @chart.markdate
111 flx = @chart.dateToX(@chart.markdate)
112 @markdateLineX = flx if flx
113 end
114
105115 end
106116
107117 # Generate the actual scale cells.
4848 @y = y + chart.header.height + 1
4949 # The height of the line in screen pixels.
5050 @height = height
51
5152 # The index of the line in the chart. It starts with 0 and is
5253 # incremented for each line by one.
5354 @lineIndex = lineIndex
9293 # Render the 'now' line
9394 if @chart.header.nowLineX
9495 div << rectToHTML(@chart.header.nowLineX, 0, 1, @height, 'nowline')
96 end
97
98 # Render the 'markdate' line
99 if @chart.header.markdateLineX
100 div << rectToHTML(@chart.header.markdateLineX, 0, 1, @height, 'markdateline')
95101 end
96102
97103 div
9595
9696 # Generate an additional VEVENT entry for all leaf tasks that aren't
9797 # milestones.
98 if task.leaf? && !task['milestone', scenarioIdx]
98 if task.leaf? && !task['milestone', scenarioIdx] && @report.get('novevents') == [false]
9999 event = ICalendar::Event.new(
100100 @ical, "#{task['projectid', scenarioIdx]}-#{task.fullId}",
101101 task.name, task['start', scenarioIdx], task['end', scenarioIdx])
296296 if @name == '.'
297297 $stdout.write(@content.to_tjp)
298298 else
299 fileName = absoluteFileName(@name)
299 fileName = @name
300300 fileName += a('definitions').include?('project') ? '.tjp' : '.tji'
301301 File.open(fileName, 'w') { |f| f.write(@content.to_tjp) }
302302 end
5959 @alignment = :center
6060 # Horizontal padding between frame and cell content
6161 @padding = 3
62 # Whether or not to indent the cell. If not nil, it is a Fixnum
62 # Whether or not to indent the cell. If not nil, it is an Integer
6363 # indicating the indentation level.
6464 @indent = nil
6565 # The basename of the icon file
3131 'activetasks' => [ 'Active Tasks', true, :right, true ],
3232 'annualleave' => [ 'Annual Leave', true, :right, true ],
3333 'annualleavebalance'=> [ 'Annual Leave Balance', false, :right, true ],
34 'annualleavelist' => [ 'Annual Leave List', false, :left, true ],
3435 'alert' => [ 'Alert', true, :left, false ],
3536 'alertmessages' => [ 'Alert Messages', false, :left, false ],
3637 'alertsummaries' => [ 'Alert Summaries', false, :left, false ],
7879 @@propertiesByType = {
7980 # Type Indent Align
8081 DateAttribute => [ false, :left ],
81 FixnumAttribute => [ false, :right ],
82 IntegerAttribute => [ false, :right ],
8283 FloatAttribute => [ false, :right ],
8384 ResourceListAttribute => [ false, :left ],
8485 RichTextAttribute => [ false, :left ],
337338 when 'chart'
338339 # For the 'chart' column we generate a GanttChart object. The sizes are
339340 # set so that the lines of the Gantt chart line up with the lines of the
340 # table.
341 # table
341342 gantt = GanttChart.new(a('now'),
342 a('weekStartsMonday'), columnDef, self)
343 a('weekStartsMonday'), columnDef, self, a('markdate'))
343344
344345 gantt.generateByScale(rStart, rEnd, columnDef.scale)
345346 # The header consists of 2 lines separated by a 1 pixel boundary.
866867 # the next cell.
867868 def genCalChartTaskCell(query, line, columnDef, t, sameTimeNextFunc)
868869 task = line.property
869 # Find out if we have an enclosing resource scope.
870 if line.scopeLine && line.scopeLine.property.is_a?(Resource)
871 resource = line.scopeLine.property
872 else
873 resource = nil
874 end
875870
876871 # Get the interval of the task. In case a date is invalid due to a
877872 # scheduling problem, we use the full project interval.
10471042 'busy'
10481043 elsif workLoad > 0.0 && freeLoad > 0.0
10491044 'loaded'
1050 elsif workLoad == 0.0 && freeLoad > 0.0
1051 'free'
1052 else
1045 elsif workLoad == 0.0 && freeLoad == 0.0
10531046 cell.tooltip = nil
10541047 'offduty'
1048 else
1049 'free'
10551050 end
10561051 end
10571052 cell.category += line.subLineNo % 2 == 1 ? '1' : '2'
264264 if isLeafTask
265265 a('scenarios').each do |scenarioIdx|
266266 generateAttribute(task, 'start', indent + 2, scenarioIdx)
267 if task['milestone', scenarioIdx]
268 if task['scheduled', scenarioIdx]
269 generateAttributeText('milestone', indent + 2, scenarioIdx)
270 end
271 else
267 if !task['milestone', scenarioIdx]
272268 generateAttribute(task, 'end', indent + 2, scenarioIdx)
273269 generateAttributeText('scheduling ' +
274270 (task['forward', scenarioIdx] ?
0 VERSION = '3.7.1'
33
44 To analyze the impact that a small variation can have on a project,
55 TaskJuggler supports an unlimited amount of scenarios. Each
6 additional scenario is a slight derivation of the it's parent. The
6 additional scenario is a slight derivation of it's parent. The
77 task tree structure needs to be the same for all scenarios, but most
88 attributes can vary from one scenario to another. Several report
99 types support comparative listing of multiple [[scenarios]].
222222 contributors that have not submitted their report.
223223
224224 # On Monday the project managers need to review the time sheets and
225 update the plan accordingly. TaskJuggler can compile a list changes
225 update the plan accordingly. TaskJuggler can compile a list of changes
226226 compared to the plan. This makes it easy to update the plan according
227227 to the actual progress that was made. The closer the actuals match the
228228 plan the less work this is. The project managers now generate
229229 bookings for the last week and add them to the database with previous
230 bookings. Doing so, will prevent changes to the plan to affect the
230 bookings. Doing so will prevent changes to the plan to affect the
231231 past. Only the future will be modified.
232232
233233 # Once the plan has been updated, managers will receive their status
695695
696696 When you run ''''tj3 --freeze'''' again, it will update the header
697697 and booking files. Since you have included your booking file, any
698 modifications you have made, will be preserved. That is, the actual
698 modifications you have made will be preserved. That is, the actual
699699 data will be preserved, not the formatting since the file will be
700700 completely re-generated again.
701701
721721 report template. Each manager will get one template that includes the
722722 status reports for the tasks they are responsible for.
723723
724 It's not the managers task to prepare the report for the next level
724 It's the managers task to prepare the report for the next level
725725 of management. To do this, the manager has 3 options:
726726
727727 * Forward the status report of a task directly to the next level. The
728 original authorship can be keep or removed. The content can also be
728 original authorship can be kept or removed. The content can also be
729729 edited if needed.
730730
731731 * Similar reports for a task or a whole task sub-tree can be combined
746746 ==== The Status Sheet Template Sender ====
747747
748748 To send out the time sheets, the command ''''tj3ts_sender'''' must be
749 used. It will use the ''''tj3client'''' program to do retrieve the
749 used. It will use the ''''tj3client'''' program to retrieve the
750750 necessary data from the TaskJuggler server.
751751
752752 Before the program can be used, a new section must be added to the
812812
813813 ==== The Status Sheet Receiver ====
814814
815 Similarly to the time sheets a the completed status sheets must be
815 Similarly to the time sheets, the completed status sheets must be
816816 send back by email. We already described how the necessary email
817817 aliases should be configured. For status sheets the address
818818 ''''statussheets@taskjuggler.your_company.com'''' can be used.
8787 you can also install it into your home or data directory. This does
8888 not require root or admin permissions.
8989
90 The following steps are describe the installation on a Linux system
90 The following steps describe the installation on a Linux system
9191 with the bash shell. You may have to use slightly different commands
9292 on a different operating system.
9393
118118 The last two settings should also be added to your .profile file to
119119 make them permanent.
120120
121 That's it. You now should be run TaskJuggler.
121 That's it. You now should run TaskJuggler.
122122
123123 tj3 --version
124124
186186
187187 git clone git@github.com/taskjuggler/TaskJuggler.git
188188
189 Make sure, you have removed all previously installed instances of
189 Make sure you have removed all previously installed instances of
190190 TaskJuggler from your system before doing so. It is a common mistake
191191 to have an old version of the TaskJuggler installed and then use parts
192192 of the old and new version together.
322322
323323 which ruby
324324
325 should show return the path to the link to your
325 should return the path to the link to your
326326 ''''${HOME}/bin/ruby''''. You now have the latest Ruby installed and
327327 are ready to use TaskJuggler.
328328
342342 file editing. If you don't have a preference yet, we recommend to try
343343 the [http://www.vim.org Vim] text editor. It's a very powerful editor
344344 and it has been customized for better integration with TaskJuggler.
345 This section describes, how to activate and use the Vim integration.
345 This section describes how to activate and use the Vim integration.
346346 Vim is provided by pretty much any Linux distribution and also works
347347 well on MacOX and Windows. See the web page for how to install it if
348348 you don't have it yet.
365365
366366 cp `gem contents taskjuggler | fgrep tjp.vim` .vim/syntax
367367
368 Now we have to make sure, Vim detects the file. Edit the
368 Now we have to make sure Vim detects the file. Edit the
369369 ''''.vim/filetype.vim'''' file to contain the following section.
370370
371371 augroup filetypedetect
2828 ''''f2'''' assigned.
2929
3030 The same works for scenarios as well. Even though the syntax may not
31 look like inheritance is at play the scenario ''''s2'''' inherits all
31 look like inheritance is at play, the scenario ''''s2'''' inherits all
3232 values from ''''s1''''.
3333
3434 <[example file="ListAttributes" tag="scenario"]>
125125 You can also insert raw HTML code by enclosing it in
126126 '''<nowiki><html>...</html></nowiki>''' tags. For all other output
127127 formats, this content will be ignored. There is also no error checking
128 if the code is valid! Use this feature very carefully.
128 whether the code is valid! Use this feature very carefully.
129129
130130 ==== Block and Inline Generators ====
131131
178178
179179 * ''''attributes'''': A set of attributes that override the original
180180 attributes of the referenced report. All report attributes
181 are supported. Since the value of attributes already must be enclosed
181 are supported. Since the values of attributes already must be enclosed
182182 by single or double quotes, all single or double quotes contained in
183183 the string must be escaped with backslashes. This feature enables
184184 reports with content that is customized based on where they have been
185185 referenced from. It requires the reports to be dynamically generated
186 and is only available when used with the ''''tj3d'''' web server.
186 and is only available when used with the ''''tj3d'''' web server
187 ''''tj3webd''''.
187188 The ''''tj3'''' application will ignore the attributes setting.
188189
189190 taskreport "All" {
253254 predefined values. When used in the header section of a report, the
254255 context does not provide a property or scope property. Start and end
255256 dates as well the formatting options are taken from the report
256 context. But when used e. g. in [[celltext.column]] the cell
257 provides, that property and the attribute and possibly even the scope
257 context. But when used e. g. in [[celltext.column]], the cell
258 provides that property and the attribute and possibly even the scope
258259 property.
259260
260261
00 == The TaskJuggler Software ==
11
2 After the installation of a software package the first questions that
2 After the installation of a software package the first question that
33 most users have is ''"How do I run it?"''. Many users expect to find
44 an icon on their desktop or an entry in the start menu hierarchy.
55 Don't bother looking for them, you won't find any for TaskJuggler. As
7979
8080 The latter defaults to using the
8181 [http://www.mozilla.com/en-US/firefox/new/ Mozilla Firefox] web
82 browser . Please see
82 browser. Please see
8383
8484 tj3man --help
8585
101101 automatically disconnects from the terminal and runs in the
102102 background. All interactions with the server are done via the TCP/IP
103103 protocol. For security reasons, only connections from the same
104 machine (localhost) are accepted. To get access all clients must
104 machine (localhost) are accepted. To get access, all clients must
105105 provide an authentication key. A TaskJuggler server can serve any
106106 number of projects. Once a project has been loaded successfully,
107107 clients can retrieve the data in form of reports. Projects are
108108 identified by their project ID. If a newly added project has the same
109 ID such as an already loaded project, the new project will replace
109 ID as an already loaded project, the new project will replace
110110 the old project once it was scheduled successfully. Before you start
111111 the server, you need to provide a configuration file with some basic
112112 settings.
146146 * 3: Like 2, but additionally with information messages
147147 * 4: Like 3, but additionally with debug messages
148148
149 The configuration file will be searched in the current directory,
149 The configuration file will be searched for in the current directory,
150150 the current user's home directory or ''''/etc''''. You can also
151151 explicitly tell the server where to find the configuration file with
152152 the ''''-c'''' option. See
209209 authKey: topsecret
210210 webServerPort: 8080
211211
212 To access the HTML reports point your web browser to
212 To access the HTML reports, point your web browser to
213213 ''''http://localhost:8080/taskjuggler''''. This assumes that the
214214 server is running on your local machine. You will then see a list of
215215 all loaded projects. Click on the project name to get a list of all
2525 The scheduler needs to determine the start and end date for all tasks
2626 that don't have such dates yet. To deal with multiple concurrent time
2727 zones, all time related events are stored internally as UTC
28 time.Additionally, it allocates resources to tasks. All events such
28 time. Additionally, it allocates resources to tasks. All events such
2929 as start or end of a task, or allocation of a resource can only happen
3030 aligned with the [[timingresolution|timing resolution]]. This
3131 determines the smallest possible allocation period that we call a time
5656 resources have been assigned for all time slots.
5757
5858 The goal of the scheduler is to transfer all tasks in the completed
59 state. Until this goal has been reached, at least one tasks needs to
59 state. Until this goal has been reached, at least one task needs to
6060 be in the ready state. If that's not the case, the project schedule
6161 cannot be determined and an error is raised. In case there are more
6262 than one task in the ready state, we need to have a well defined
102102 the tasks of the path is computed. The largest sum is the path
103103 criticalness of that task.
104104
105 This heuristic will favor allocations to task with critical resources
105 This heuristic will favor allocations to tasks with critical resources
106106 and long dependency chains. As a result, the critical paths of the
107107 project are tried to be kept short. The user can use the
108108 '''criticalness''' and '''pathcriticalness''' [[columnid|columns]] to
110110
111111 When the criticalness and pathcriticalness for all leaf resources and
112112 tasks has been determined, the leaf tasks are sorted by priority
113 (hight to low), then by pathcricialness (high to low) and then by the
113 (high to low), then by pathcricialness (high to low) and then by the
114114 index (low to high). In a loop that is terminated when all tasks have
115115 been scheduled or an error condition has been detected, the first
116116 task that is ready for scheduling is completely scheduled. This means
3333 keyword ( foo | bar | foobar )
3434
3535 Some keywords take one or more arguments. These are known as list
36 attributes. The arguments are comma separated. The tree dots in the
36 attributes. The arguments are comma separated. The three dots in the
3737 syntax description mean that the sequence before the dots can be
3838 repeated if needed. Inheritable list attributes will append the new
3939 list values to the inherited list. Use can use the [[purge]]
7272
7373 Strings are character sequences that are enclosed by special
7474 character marks. There are three different marks supported. For
75 short strings that fit on one lines, you can either use single or
75 short strings that fit on one line, you can either use single or
7676 double quotes.
7777
7878 'This is a single quoted string.'
111111 === Predefined Macros ===
112112
113113 TaskJuggler supports a few predefined macros. These are available
114 after the project header. They values correspond to the values
114 after the project header. Their values correspond to the values
115115 provided in the project header.
116116
117117 * ''''projectstart'''' The start date of the project.
127127 === Environment Variable Expansions ===
128128
129129 By using the $(VAR) syntax, you can insert the value of the
130 environment variable name VAR. The name of the variable must consists
131 only of uppercase ASCII letters, underscore or decimal digits.
130 environment variable name VAR. The name of the variable must consist
131 only of uppercase ASCII letters, underscores or decimal digits.
132132
1212 TaskJuggler software installation. You can use the following command
1313 to find the base directory of the example projects.
1414
15 ruby19 -e "puts Gem::Specification.find_by_name('taskjuggler').gem_dir"
15 ruby -e "puts Gem::Specification.find_by_name('taskjuggler').gem_dir"
1616
1717 The file for the tutorial project is called
1818 ''''examples/Tutorial/tutorial.tjp''''. You can use any plain text
3030
3131 <[example file="tutorial" tag="header1"]>
3232
33 All TaskJuggler properties have a unique ID ,a name, and a set of
33 All TaskJuggler properties have a unique ID, a name, and a set of
3434 optional attributes. The name must always be specified. The ID can be
3535 omitted if you never have to reference the property from another
3636 context. If you omit the ID, TaskJuggler will automatically generate a
7474 <[example file="tutorial" tag="currency"]>
7575
7676 Because each culture has its own way of specifying dates and numbers,
77 the format for these are configurable. Use the [[timeformat]]
77 the format for these is configurable. Use the [[timeformat]]
7878 attribute to specify the default format for dates. This format is used
7979 for reports, it does not affect the way you specify dates in the
8080 project files. Here you always need to use the [[date|TaskJuggler date
147147
148148 Use the [[leaves]] attribute to define a global holiday. Global
149149 holidays may have a name and must have a date or date range. Other leaves for
150 individual resources or groups of resources can be defines similarly.
150 individual resources or groups of resources can be defined similarly.
151151
152152 === Macros ===
153153
188188 [[account|accounts]] to credit the amounts to. We create one account
189189 for the development costs, one for the documentation costs, and one
190190 for the customer payments.
191 Actually, there is a fourth account consisting of two accounts nested
192 into it.
191193
192194 <[example file="tutorial" tag="accounts"]>
193195
307309 resources could be allocated long enough to reach the specified
308310 effort. Tasks with ''''length'''' or ''''duration'''' criteria and
309311 allocated resources will last exactly as long as requested. Resources
310 will be allocated only if available. It's possible that such a tasks
312 will be allocated only if available. It's possible that such a task
311313 ends up with no allocations at all if the resources are always
312314 assigned to other tasks for that period. Each task can only have one
313315 of the three duration criteria. Container tasks may never have a
330332 specification. The start and end criteria can either be fixed dates or
331333 relative dates. Relative dates are specifications of the type ''task B
332334 starts after task A has finished''. Or in other words, task B depends
333 on task A. In this example the spec task depends on a subtasks of the
335 on task A. In this example the spec task depends on a subtask of the
334336 deliveries task. We have not specified it yet, but it has the local ID
335337 ''''start''''.
336338
346348 Relative IDs always start with one or more exclamation marks. Each
347349 exclamation mark moves the scope to the next enclosing task. So
348350 ''''!deliveries.start'''' is expanded to ''''AcSo.deliveries.start''''
349 since ''''AcSo'''' is the enclosing task of deliveries. Relative task
351 since ''''AcSo'''' is the enclosing task of ''''deliveries''''. Relative task
350352 IDs are a little bit confusing at first, but have a real advantage
351353 over absolute IDs. Sooner or later you want to move tasks around in
352354 your project and then it's a lot less likely that you have to fix
361363 the tasks. 500 is the default priority of top-level tasks. Setting the
362364 priority to 1000 marks the task as most important task, since the
363365 possible range is 1 (not important at all) to 1000 (ultimately
364 important). priority is an attribute that is passed down to subtasks
366 important). ''''priority'''' is an attribute that is passed down to subtasks
365367 if specified before the subtasks' declaration. So all subtasks of
366368 software have a priority of 1000 as well, unless they have their own
367369 priority definition.
485487
486488 === Visualizing the Project ===
487489
488 To see and share the project data you reports can be generated. You
490 To see and share the project data, reports can be generated. You
489491 can generate any number of reports and you can select from a variety
490492 of report types and output formats. To have a report generated after
491493 the project scheduling has been completed, you need include a report
644646 report file.
645647
646648 For the [[footer]] we can proceed accordingly. We just add a few more
647 paragraphs of text the describe certain aspects of the project. By
649 paragraphs of text to describe certain aspects of the project. By
648650 putting it all together, we end up with the following report
649651 definition.
650652
652654
653655 The generated report can be found
654656 [http://www.taskjuggler.org/tj3/examples/Tutorial/Overview.html
655 here]. It servers as an entry page for the other reports. While it
657 here]. It serves as an entry page for the other reports. While it
656658 already contains some references, a navigator bar would be handy as
657659 well. Fortunately, there is a block generator called 'navigator' to
658660 take care of this. But before we can include the navigator in the
8181
8282 it "should fail with bad authentication key" do
8383 TaskJuggler::runBroker(@pb, @authKey) do
84 @pbi.command('bad key', :status, []).should be_false
84 @pbi.command('bad key', :status, []).should be false
8585 end
8686 end
8787
104104 stdOut = StringIO.new
105105 stdErr = StringIO.new
106106 args = [ Dir.getwd, [ '.' ], stdOut, stdErr, stdIn, true ]
107 @pbi.command(@authKey, :addProject, args).should be_true
107 @pbi.command(@authKey, :addProject, args).should be true
108108 stdErr.string.should be_empty
109109
110110 # Can't remove non-existing project bar
111 @pbi.command(@authKey, :removeProject, 'bar').should be_false
112 @pbi.command(@authKey, :removeProject, 'foo').should be_true
111 @pbi.command(@authKey, :removeProject, 'bar').should be false
112 @pbi.command(@authKey, :removeProject, 'foo').should be true
113113 # Can't remove foo twice
114 @pbi.command(@authKey, :removeProject, 'foo').should be_false
114 @pbi.command(@authKey, :removeProject, 'foo').should be false
115115 end
116116 end
117117
122122 it "should fail with bad authentication key" do
123123 TaskJuggler::runBroker(@pb, @authKey) do
124124 @pbi.updateState('bad key', 'foo', 'foo', :status, true).should \
125 be_false
125 be false
126126 end
127127 end
128128
229229 it 'should have matching status sheets in body and attachment' do
230230 @sss_mails.each do |mail|
231231 bodySheet = extractStatusSheet(mail.parts[0].decoded)
232 attachedSheet = extractStatusSheet(mail.part[1].decoded)
232 attachedSheet = extractStatusSheet(mail.part[1].decoded).tr("\r", '')
233233 bodySheet.should == attachedSheet
234234 end
235235 end
215215 it 'should have matching timesheets in body and attachment' do
216216 @tss_mails.each do |mail|
217217 bodySheet = extractTimeSheet(mail.parts[0].decoded)
218 attachedSheet = extractTimeSheet(mail.part[1].decoded)
218 attachedSheet = extractTimeSheet(mail.part[1].decoded).tr("\r", '')
219219 bodySheet.should == attachedSheet
220220 end
221221 end
3434 s.summary = 'A Project Management Software'
3535 s.description = <<'EOT'
3636 TaskJuggler is a modern and powerful, Free and Open Source Software project
37 management tool. Its new approach to project planing and tracking is more
37 management tool. It's new approach to project planning and tracking is more
3838 flexible and superior to the commonly used Gantt chart editing tools.
3939
4040 TaskJuggler is project management software for serious project managers. It
4141 covers the complete spectrum of project management tasks from the first idea
4242 to the completion of the project. It assists you during project scoping,
43 resource assignment, cost and revenue planing, risk and communication
43 resource assignment, cost and revenue planning, risk and communication
4444 management.
4545 EOT
46
46 s.license = 'GPL-2.0'
4747 s.require_path = 'lib'
4848 s.files = (`git ls-files -- lib`).split("\n") +
4949 (`git ls-files -- data`).split("\n") +
5252 (`git ls-files -- tasks`).split("\n") +
5353 %w( .gemtest taskjuggler.gemspec Rakefile ) +
5454 # Generated files, not contained in Git repository.
55 %w( data/tjp.vim ) + Dir.glob('manual/html/**/*')
55 %w( data/tjp.vim ) + Dir.glob('manual/html/**/*') + Dir.glob('man/*.1')
5656 s.bindir = 'bin'
5757 s.executables = (`git ls-files -- bin`).split("\n").
5858 map { |fn| File.basename(fn) }
6262 s.has_rdoc = true
6363 s.extra_rdoc_files = %w( README.rdoc COPYING CHANGELOG )
6464
65 s.add_dependency('mail', '>= 2.4.3')
66 s.add_dependency('term-ansicolor', '>= 1.0.7')
67 s.add_development_dependency('rspec', '>= 2.5.0')
65 s.add_dependency('mail', '~> 2.7', '>= 2.7.1')
66 s.add_runtime_dependency('term-ansicolor', '~> 1.7', '>= 1.7.1')
67 s.add_development_dependency('rspec', '~> 2.5', '>= 2.5.0')
6868 s.platform = Gem::Platform::RUBY
6969 s.required_ruby_version = '>= 2.0.0'
7070 }
00 require 'time'
1
2 CLOBBER.include "CHANGELOG"
13
24 desc 'Generate the CHANGELOG file'
35 task :changelog do
11 require 'find'
22 require 'rubygems'
33 require 'rubygems/package'
4
5 CLOBBER.include "pkg/"
46
57 # Unfortunately Rake::GemPackageTest cannot deal with files that are generated
68 # by Rake targets. So we have to write our own packaging task.
1012 Rake::Task[:manual].invoke
1113 Rake::Task[:changelog].invoke
1214 Rake::Task[:permissions].invoke
15 Rake::Task[:help2man].invoke
1316
1417 load 'taskjuggler.gemspec';
1518
0 # TASK MAN GENERATE
1
2 CLOBBER.include "man"
3
4 directory "man"
5
6 desc 'Generate man pages from help'
7 task :help2man => 'man' do
8 help2man = %x{which help2man}
9 help2man.chomp!
10 Dir.foreach('bin') do |prog|
11 next if prog == '.' or prog == '..'
12 system help2man,"--output=man/#{prog}.1","--no-info","--manual=TaskJuggler",*("--include=h2m/#{prog}.h2m" unless !File.exists?("h2m/#{prog}.h2m")),"bin/#{prog}"
13 FileUtils.chmod(0644, "man/#{prog}.1")
14 end
15 FileUtils.chmod(0755, 'man')
16 end
17
00 # TASK Kate SYNTAX
11
22 require 'taskjuggler/KateSyntax'
3
4 CLOBBER.include "data/kate-tjp.xml"
35
46 desc 'Generate kate-tjp.xml Kate syntax file'
57 task :kate do
00 # TASK MANUAL
11
22 require 'taskjuggler/apps/Tj3Man'
3
4 CLOBBER.include "manual/html/"
35
46 desc 'Generate User Manual'
57 task :manual do
00 $:.unshift File.join(File.dirname(__FILE__), '..', 'test')
11
22 require 'rake/testtask'
3
4 CLEAN.include "test/TestSuite/Export-Reports/refs/Leave.tjp"
5 CLEAN.include "test/TestSuite/Export-Reports/refs/ListAttributes.tjp"
6 CLEAN.include "test/TestSuite/Export-Reports/refs/Macro-4.tjp"
7 CLEAN.include "test/TestSuite/Export-Reports/refs/TraceReport.tjp"
38
49 # TEST TASK
510 desc 'Run all unit tests in the test directory'
00 # TASK VIM SYNTAX
11
22 require 'taskjuggler/VimSyntax'
3
4 CLOBBER.include "data/tjp.vim"
35
46 desc 'Generate vim.tjp Vim syntax file'
57 task :vim do
4444 task _Task_6 "Final Payment" {
4545 depends _Task_1.mf
4646 start 2012-10-22-17:00-+0000
47 milestone
4847 scheduled
4948 }
5049 }
99
1010 task t1 "T1" {
1111 start 2011-03-05-00:00-+0000
12 milestone
1312 scheduled
1413 }
1514 task t2 "T2" {
1615 start 2011-03-05-00:00-+0000
17 milestone
1816 scheduled
1917 }
2018 task t3 "T3" {
1414
1515 task _Task_1 "Holiday Season" {
1616 start 2011-11-24-00:00-+0000
17 milestone
1817 scheduled
1918 }
2019 supplement task _Task_1 {
2424 }
2525 task m1 "Milestone 1" {
2626 start 2003-06-05-06:00-+0000
27 milestone
2827 scheduled
2928 }
3029 }
3131 task _Task_1 "Foo" {
3232 task _Task_2 "Bar" {
3333 start 2009-10-04-00:00-+0000
34 milestone
3534 scheduled
3635 }
3736 }
99
1010 task items "Project breakdown" {
1111 start 2006-09-22-00:00-+0000
12 milestone
1312 scheduled
1413 }
1514 supplement task items {
99
1010 task t "Task" {
1111 start 2007-01-01-00:00-+0000
12 milestone
1312 scheduled
1413 }
1514 supplement task t {
3737
3838 task _Task_1 "T" {
3939 start 2013-04-24-00:00-+0000
40 milestone
4140 scheduled
42 two:milestone
4341 }
4442 supplement task _Task_1 {
4543 Claim "A '''big''' statement."
1010 task foo1 "foo1" {
1111 task foo2 "foo2" {
1212 start 2007-12-04-07:00-+0000
13 milestone
1413 scheduled
1514 }
1615 task foo3 "foo3" {
1717 }
1818 task intervalTask "Interval Task" {
1919 start 2007-06-17-06:00-+0000
20 milestone
2120 scheduled
2221 }
2322 task lengthTask "Length Task" {
1313
1414 task t "An important date" {
1515 start 2007-07-21-06:00-+0000
16 milestone
1716 scheduled
1817 }
1918 supplement task t {
99
1010 task t1 "Task 1" {
1111 start 2005-05-29-06:00-+0000
12 milestone
1312 scheduled
1413 }
1514 task t2 "Task 2" {
1615 depends t1
1716 start 2005-06-03-06:00-+0000
18 milestone
1917 scheduled
2018 }
2119 task t3 "Task 3" {
2220 depends t1
2321 start 2005-06-03-23:00-+0000
24 milestone
2522 scheduled
2623 }
2724 supplement task t1 {
1313
1414 task _Task_1 "Foo" {
1515 start 2010-02-26-00:00-+0000
16 milestone
1716 scheduled
1817 }
1918 supplement task _Task_1 {
1010
1111 task t1 "Task1" {
1212 start 2009-05-05-06:00-+0000
13 milestone
1413 scheduled
1514 }
1615 supplement task t1 {
1111
1212 task t1 "Task1" {
1313 start 2008-01-18-00:00-+0000
14 milestone
1514 scheduled
1615 }
1716 task t2 "Task2" {
99
1010 task _Task_1 " Crème brûlée Prepare " {
1111 start 2010-04-28-00:00-+0000
12 milestone
1312 scheduled
1413 }
1514 task _Task_2 "task" {
1615 start 2010-04-28-00:00-+0000
17 milestone
1816 scheduled
1917 }
2018 supplement task _Task_1 {
99
1010 task _Task_1 "foo" {
1111 start 2009-12-01-00:00-+0000
12 milestone
1312 scheduled
1413 }
1514 supplement task _Task_1 {
2222
2323 task _Task_1 "T" {
2424 start 2010-04-03-00:00-+0000
25 milestone
2625 scheduled
2726 }
2827 supplement task _Task_1 {
99
1010 task project_start "Project Start" {
1111 start 2005-07-15-06:00-+0000
12 milestone
1312 scheduled
1413 }
1514 task deadline "Important Deadline" {
1615 start 2005-07-20-06:00-+0000
17 milestone
1816 scheduled
1917 }
2018 supplement task project_start {
99
1010 task t "Task" {
1111 start 2000-01-01-00:00-+0000
12 milestone
1312 scheduled
1413 }
1514 supplement task t {
1010 task foo1 "foo1" {
1111 task foo2 "foo2" {
1212 start 2003-12-04-07:00-+0000
13 milestone
1413 scheduled
1514 }
1615 task foo3 "foo3" {
99
1010 task t "Task" {
1111 start 2007-01-01-07:00-+0000
12 milestone
1312 scheduled
1413 }
1514 supplement task t {
99
1010 task t1 "Task 1" {
1111 start 2006-08-22-06:00-+0000
12 milestone
1312 scheduled
1413 }
1514 task t2 "Task 2" {
1615 start 2006-08-22-06:00-+0000
17 milestone
1816 scheduled
1917 }
2018 task t3 "Task 3" {
2119 start 2006-08-22-06:00-+0000
22 milestone
2320 scheduled
2421 }
2522 supplement task t1 {
2929 }
3030 task t3 "FooTask3" {
3131 start 2000-01-01-07:00-+0000
32 milestone
3332 scheduled
3433 }
3534 supplement task t1 {
1414
1515 task t "An important date" {
1616 start 2005-06-10-06:00-+0000
17 milestone
1817 scheduled
1918 }
2019 supplement task t {
1818
1919 task _Task_1 "T" {
2020 start 2010-11-10-00:00-+0000
21 milestone
2221 scheduled
2322 }
2423 supplement task _Task_1 {
1818
1919 task _Task_1 "T" {
2020 start 2010-11-10-00:00-+0000
21 milestone
2221 scheduled
2322 }
2423 supplement task _Task_1 {
1515
1616 task t "Task" {
1717 start 2007-05-29-06:00-+0000
18 milestone
1918 scheduled
2019 actual:start 2007-06-03-06:00-+0000
21 actual:milestone
2220 }
2321 supplement task t {
2422 priority 500
99
1010 task item "Project" {
1111 start 2005-06-06-09:00-+0000
12 milestone
1312 scheduled
1413 }
1514 supplement task item {
1515
1616 task t "An important date" {
1717 start 2005-07-22-06:00-+0000
18 milestone
1918 scheduled
2019 }
2120 supplement task t {
1010 task foo "Foo" {
1111 task _Task_2 "Foo 1" {
1212 start 2011-12-12-00:00-+0000
13 milestone
1413 scheduled
1514 }
1615 task _Task_3 "Foo 2" {
1716 start 2011-12-12-00:00-+0000
18 milestone
1917 scheduled
2018 }
2119 }
2220 task bar "Bar" {
2321 task _Task_5 "Bar 1" {
2422 start 2011-12-12-00:00-+0000
25 milestone
2623 scheduled
2724 }
2825 task _Task_6 "Bar 2" {
2926 start 2011-12-12-00:00-+0000
30 milestone
3127 scheduled
3228 }
3329 }
1717 task wp1 "Workpackage 1" {
1818 task t1 "Task 1" {
1919 start 2011-11-11-05:00-+0000
20 milestone
2120 scheduled
2221 }
2322 task t2 "Task 2" {
2423 start 2011-11-11-05:00-+0000
25 milestone
2624 scheduled
2725 }
2826 }
3028 depends project.wp1
3129 task t1 "Task 1" {
3230 start 2011-11-11-05:00-+0000
33 milestone
3431 scheduled
3532 }
3633 task t2 "Task 2" {
3734 start 2011-11-11-05:00-+0000
38 milestone
3935 scheduled
4036 }
4137 }
4339 task _Task_9 "Item 1" {
4440 depends project.wp1
4541 start 2011-11-11-05:00-+0000
46 milestone
4742 scheduled
4843 }
4944 task _Task_10 "Item 2" {
5045 depends project.wp2
5146 start 2011-11-11-05:00-+0000
52 milestone
5347 scheduled
5448 }
5549 }
99
1010 task _Task_1 "Foo" {
1111 start 2011-12-11-00:00-+0000
12 milestone
1312 scheduled
1413 }
1514 supplement task _Task_1 {
103103 task deliveries "Milestones" {
104104 task start "Project start" {
105105 start 2002-01-16-00:00-+0000
106 milestone
107106 scheduled
108107 delayed:start 2002-01-19-23:00-+0000
109 delayed:milestone
110108 }
111109 task prev "Technology Preview" {
112110 depends AcSo.software.backend
113111 start 2002-02-28-14:00-+0000
114 milestone
115112 scheduled
116113 delayed:start 2002-03-05-14:00-+0000
117 delayed:milestone
118114 }
119115 task beta "Beta version" {
120116 depends AcSo.test.alpha
121117 start 2002-04-03-10:00-+0000
122 milestone
123118 scheduled
124119 delayed:start 2002-04-11-09:00-+0000
125 delayed:milestone
126120 }
127121 task done "Ship Product to Customer" {
128122 depends AcSo.test.beta, AcSo.manual
129123 start 2002-04-18-13:00-+0000
130 milestone
131124 scheduled
132125 delayed:start 2002-04-26-12:00-+0000
133 delayed:milestone
134126 }
135127 }
136128 }
1919 2007-01-09-13:00 +4h
2020 # This is a common mistake. With standard working hours, this will
2121 # yield a zero time booking! The interval is midnight to 8am. So
22 # it's outside of the working hours and 'sloppy 2' surpresses the
22 # it's outside of the working hours and 'sloppy 2' suppresses the
2323 # warning.
2424 booking test 2007-01-11 +8h { sloppy 2 }
2525 # Use 'overtime' to book off-hour slots. This booking will book the
00 project prj "Project" "1.0" 2007-01-01 - 2007-03-01 {
11 timezone "Europe/Berlin"
22 # German currency format: e. g. -10.000,20 5.014,11
3 numberformat "-" "" "." "," 2
3 currencyformat "-" "" "." "," 2
44
55 # US currency format: e. g. (10,000.20) 5,014.11
66 currencyformat "(" ")" "," "." 2
3232 # *** EXAMPLE: now +
3333 now 2002-03-05-13:00
3434 # *** EXAMPLE: now -
35 # The date that is used to show additional line on a Gannt chart
36 # and can be specified by the user.
37 # *** EXAMPLE: markdate +
38 markdate 2002-08-07-03:00
39 # *** EXAMPLE: markdate -
3540 # The currency for all money values is the Euro.
3641 # *** EXAMPLE: currency +
3742 currency "USD"
5555 [:LITERAL, '-', 6],
5656 [:LITERAL, '$', 6],
5757 [:MACRO, 'A Macro', 6],
58 [:TIME, time(15, 23), 7],
58 [:TIME, mktime(15, 23), 7],
5959 [:STRING, 'A string', 7],
6060 [:STRING, "It's a string", 8],
6161 [:STRING, "A\nmult\"i line\nstring", 9],
100100 24:00
101101 EOT
102102 ref = [
103 [:TIME, time(0, 0), 1],
104 [:TIME, time(0, 0), 2],
105 [:TIME, time(1, 0), 3],
106 [:TIME, time(11, 59), 4],
107 [:TIME, time(12, 1), 5],
108 [:TIME, time(24, 0), 6],
103 [:TIME, mktime(0, 0), 1],
104 [:TIME, mktime(0, 0), 2],
105 [:TIME, mktime(1, 0), 3],
106 [:TIME, mktime(11, 59), 4],
107 [:TIME, mktime(12, 1), 5],
108 [:TIME, mktime(24, 0), 6],
109109 [:eof, '<END>', 7]
110110 ]
111111
171171
172172 private
173173
174 def time(h, m)
174 def mktime(h, m)
175175 (h * 60 + m) * 60
176176 end
177177