Clone wiki

PlSchedule / Home

PlSchedule

PlSchedule is a set of Prolog and Perl scripts to generate weekly schedules, considering all possible combinations of a given list of events.

Note: Whenever the term Prolog is used in this document, it refers to SWI Prolog. Other implementations may work, but are not tested. See requirements below.

Example

Let's take a look at a simple example: assume you have a list of events, Event 1Event 4:

Event Occurence Day Time
Event 1 all weeks Monday 11:00 — 12:30
Event 2 even weeks Monday 13:00 — 14:30
odd weeks Monday 15:00 — 16:30
Event 3 even weeks Monday 15:00 — 16:30
Event 4 even weeks Monday 13:00 — 14:30
odd weeks Monday 15:00 — 16:30

As you can see there are two alternative dates for both Event 2 and Event 4. It is PlSchedule's task to generate all possible schedules containing all events (and only one date for events with alternative dates).

The first thing to do is to create a configuration file listing these events.

The configuration file

The configuration file is actually a Prolog file, so you need to make sure to use the proper syntax. Take a look at the configuration file for the example above:

event( 'Event 1',  'A',  1,  1100,  1230,  'Some notes for event 1.'          ).
event( 'Event 2',  'E',  1,  1300,  1430,  'Some more notes | and a new line' ).
event( 'Event 2',  'O',  1,  1500,  1630,  ''                                 ).
event( 'Event 3',  'E',  1,  1500,  1630,  ''                                 ).
event( 'Event 4',  'E',  1,  1300,  1430,  'Event 4.1'                        ).
event( 'Event 4',  'O',  1,  1500,  1630,  'Event 4.2'                        ).

Every event has to be included as a Prolog fact, (event/6), the syntax is:

event( <event name>, <weeks>, <day>, <start>, <end>, <notes> ).

With the following parameters:

<event name>
The <event name> is used to distinguish different events from one another, alternative dates for one event must use the same <event name>, different events must not use the same name.
<weks>
<weeks> must be one of 'A', 'O' or 'E', specifying if the event occurs in all weeks, or only in weeks with odd week numbers or weeks with even week numbers, respectively.
<day>
Specifies the day for the event, it must be an integer, in the range of 1 (Monday) to 7 (Sunday).
<start> and <end>
Start and end times of the event. These are also specified as integers, in 24h format, without any separator between the hour and minute part, the range is 0000 to 2359. Note that there is no check for invalid numbers. You may omit leading zeroes, but it is recommended to include them for better readability.
<notes>
Arbitrary notes for the event. These are ignored by the script generating the schedules, but will be included in the output. Note that you may use a vertical bar ('|') to force a new line when generating the HTML output later on. Notes may be empty, but make sure to include an empty string in that case.

Generating the schedules

Now save the example configuration listed above in a file called events.conf in the same directory as the scripts. To generate all schedules, change to that directory and run the following command:

./schedule.pl events.conf

The command syntax is:

schedule.pl <config file> [<config file> ...]

At least one config file is mandatory, more than one config file is allowed, so you can split the config if required. You may use relative or absolute paths. The files are loaded using Prolog's consult/1 predicate.

Few things to keep in mind:

  • All Prolog code in the config file is executed, so please do not use config files from untrusted sources without checking them first!
  • If a file by a given name is not found, Prolog will append .pl to that name and try to load that file.
  • The special value user must not be used as name of a configuration file. If you do want to use it, you have to specify the file using its full path or a relative path like ./user.

The output for the example above will be something like the following (without the line breaks, and possibly also lacking some spaces):

[
  (Event 4, O, 1, 1500, 1630, Event 4.2),
  (Event 3, E, 1, 1500, 1630, ),
  (Event 2, E, 1, 1300, 1430, Some more notes | and a new line),
  (Event 1, A, 1, 1100, 1230, Some notes for event 1.)
]
[
  (Event 4, E, 1, 1300, 1430, Event 4.1),
  (Event 3, E, 1, 1500, 1630, ),
  (Event 2, O, 1, 1500, 1630, ),
  (Event 1, A, 1, 1100, 1230, Some notes for event 1.)
]

These are all possible schedules that could be generated from the example configuration.

Note: If there are conflicts in the configuration the output will be empty, in this case you need to resolve the conflicts manually.

Formatting the output

To get a more human-readable output, use the translate.pl script. It reads its input from STDIN, so you can pipe the output from the schedule.pl script into it. For the example above:

./schedule.pl events.conf | ./translate.pl

This will generate the following output (days without events are left out):

Schedule #00001:

        Monday
                11:00 - 12:30 => Event 1 | Some notes for event 1.
                13:00 - 14:30 => Event 2 [E] | Some more notes | and a new line
                15:00 - 16:30 => Event 4 [O] | Event 4.2
                15:00 - 16:30 => Event 3 [E]


Schedule #00002:

        Monday
                11:00 - 12:30 => Event 1 | Some notes for event 1.
                13:00 - 14:30 => Event 4 [E] | Event 4.1
                15:00 - 16:30 => Event 3 [E]
                15:00 - 16:30 => Event 2 [O]

As you can see the week is included in square brackets for odd and even weekly events ([O] and [E], this - as well as the names used for the days - can actually be changed in the translate.pl script if required, read the notes in the source code), and the notes (if specified for an event) are separated by a vertical bar.

The translate.pl script offers an additional feature: you can include only specific schedules in the output.

The syntax is:

schedule.pl <options> | translate.pl [<schedule> ...],

where <schedule> is the schedule number in the full output, more than one schedule may be specified. To include only the second schedule in the output, you would use:

schedule.pl <options> | translate.pl 2

Generating the HTML output

The script to generate HTML tables for the schedules is called html.pl. It reads the output of the translate.pl script from STDIN and generates HTML tables for all schedules. The resulting tables are printed to STDOUT, the original input is printed to STDERR. The tables generated are simple HTML4, and the output will only contain the tables itself, i.e. it will not be a full HTML page.

For our example the command to create the table for only schedule number 2 is:

./schedule.pl events.conf | ./translate.pl 2 | ./html.pl

or, if you want to redirect the output to the file schedule_2.html:

./schedule.pl events.conf | ./translate.pl 2 | ./html.pl >schedule_2.html

Note that the vertical bars in the output have been replaced by line breaks in the HTML code.

Finally, to create valid XHTML 1.0 Strict output, you may use the xhtml.pl script. Again, this reads its input (that is the output of the html.pl script) from STDIN, and prints the output to STDOUT. To create a valid XHTML page for schedule number 2 as schedule_2.xhtml for the example, use:

./schedule.pl events.conf | ./translate.pl 2 | ./html.pl | ./xhtml.pl >schedule_2.xhtml

Requirements

License

Copyright © 2008-2010, 2014 Stefan Göbel - <plschedule -at- subtype -dot- de>

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Updated