Plan like a Pro with Automatic Scheduling in Taskjuggler
Tags: productivity, project, management, tasks
Published: 2020-07-03 10:09:37

# The Need for Automatic Project Scheduling?
Every one of us has done some project planning in a way or another. Some people would have used fancy GANTT editing tools for that; others would just go ahead and dump their brains onto a backlog. But very few are those who follow an automatic approach to "schedule" their projects.

More often than not, people would go manually about making decisions about the gameplay to adopt facing their daunting projects. They try to envision the best possible plan while mentally trying to sort what we call "precedence constraints," i.e., one can't work on Task A before Task B and C have been achieved. They do so all while finding feasible and commercially viable resource allocation schemes. Also, they need to contort to time-bound constraints, like deadlines and seasonal phenomena.

All that makes a perfect case for an automatic scheduling tool, and [Taskjuggler](https://taskjuggler.org/) might be the most powerful - if not the only - mature alternative you have at hand. But this is not a shiny Kanban-y drag-and-drop thingy: this is a full-fledged enterprise-grade automatic project planning and estimating solution, so much that it takes some learning curve to get fluent in it, but believe me, the effort is worth it. 

# Taskjuggler: Thinking in Work Breakdown Structure
Without drowning too deep in detail, **Taskjuggler** lets you focus on your project structure. 
Rather than giving you GANTT drawing tools and letting you figure the plan out yourself, **Tasjkjuggler** asks that you give it your **Work Breakdown Structure**, and it does the scheduling for you. Simply put, A Work Breakdown Structure is a graph depicting the tasks you need to achieve, along with the relationships between them and the resources necessary to make them happen. 

**Taskjuggler** is also able to follow on the realization of the project and will adjust the plan according to the actual project roll-out. Besides, it offers you the possibility to simulate multiple scenarios.

**Taskjuggler** is also finance aware, and sports an accounting module that can track the costs inferred by the allocated resources against revenues that you'd record as you're working on your project. I have used this accounting module so many times as my secret weapon to come up with detailed financial quotes and win the commercial race!

# Taskjuggler in action
First of all, you'll need to install **Taskjuggler** [following the instructions on its website.](https://taskjuggler.org/tj3/manual/Installation.html#Installation)

**Taskjuggler** comes as a line command, *tj3*, that compiles your project descriptions into the project reports you specify. Let's run through a simple example.

Suppose you want to specify a Software Development project. We first need the data engineer to design the database, then have the web designers design the application, then have the Devops deploy it.

Let's begin by creating a file for our project. We'll name it project.tjp.

We'll begin by specifying our project name, plus some general information about it, like its start date, and what would be the deadline for it(1 month from the start, hence the +1m":
```tjp
project softdev "Software Development"  2020-08-16 +1m {
 timezone "Europe/Paris"
 currency "USD"
}
```

Let's then declare the financial accounts we'll be using to track the finances of our project:

```tjp
account cost "cost"
account rev "payments"
balance cost rev
```

We now declare the resources we need for our tasks:
```tjp
resource data_engineer "Data Engineer" {
    rate 200
}

resource web_engineer "Web Engineer" {
    rate 200
}

resource devops_engineer "Devops Engineer" {
    rate 200
}
```

*rate* will be used to give a financial estimate of our project. We are using the simplest form, but you can organize them into teams, flag them, assign managers...

Let's now get into the actual business. Next, we'll describe our Work Breakdown Structure, that is, tasks, constraints, and resources. We'll organize our tasks into to categories. **Work**, where we'll describe our actual tasks to be done, and **Milestones**, to track important steps and deliveries of our project. For this, we'll use the possibility to nest Tasks in **taskjuggler**. First, let's see the **Work** part.

```tjp
task work "Work"{
  task data "Database Design" {
    chargeset cost
    allocate data_engineer
    effort 3d # This task takes 10 days effort
  }

  task web "Web App Design" {
      chargeset cost
      allocate web_engineer
      effort 3d # This task takes 10 days effort
      depends !data  # This task needs task data to be complete
  }

  task deploy "Deployment" {
      chargeset cost
      allocate devops_engineer
      effort 3d # This task takes 10 days effort
      depends !web # This task needs task web to be complete
  }
}
```
The **chargeset** clause is used to add the costs inferred by a resource working on a task to a particular account, which is **cost** here. We'll use this account to get a quote for the whole work needed for this project.

The **depends** construct tells **Taskjuggler** that a task can't be worked on BEFORE the referred task has been achieved. This is what we call *"Precedence Constraint"* in Work Breakdown Speak.

The *depends* clause uses the exclamation mark **'!'** to refer to tasks that are one level higher in the hierarchy. For example, ***deploy*** depends on ***!web*** means that it depends on the task **web** under a direct parent(one level up), yielding its direct sibling **web**(their common parent task being **work**)

Now for the **Milestones** section:
```tjp
task milestones "Milestones" {
  task db_milestone "Database Finish" {
      # A milestone has effort 0, it's represented as a little black square
      depends !!work.data
  }

  task web_milestone "Web Finish" {
      # A milestone has effort 0, it's represented as a little black square
      depends !!work.web
  }

  task deploy_milestone "Deploy Finish" {
      # A milestone has effort 0, it's represented as a little black square
      depends !!work.deploy
  }

  task project_end_milestone "Project End" {
    depends !!work.deploy
  }
}
```
Note how now **depends** uses a double exclamation mark. Look at task **deploy_milestone** for instance. It is meant to track the completion of the **deploy** task under the **work** container task. At this level, we are under **milestones**, so we need one **!** to get to the level of the direct parent **milestones**, then another more to get the grand-parent level, under which we get to the aunt task **work** and refer **deploy** by using a familiar dotted syntax, hence the **!!work.deploy** token.

At this point, our project description is finished, but if you run it through the **taskjuggler** compiler, you won't get any output:
```shell
tj3 project.tjp
#... Truncated Output
Warning: This project has no reports defined. No output data will be generated.
Warning: None of the reports has a 'formats' attribute. No output data will be generated.
```

Indeed, you need to specify reports to get the **Taskjuggler** engine to compile the results under the format you want. And this is presumably the most complicated part. Here we go.

We'll generate a static website. The entry point to the reports is the **Overview** report page, with a link to detailed resource allocation by task under the **Development** subreport, and a link to a resource Utilization under the **Resource Graph** subreport.

This post won't dive into the **Taskjuggler** report syntax, but if you're interested, you can check it [here](https://taskjuggler.org/manual/general_usage.html). This being said, you can use the following as a template to start your pro scheduling journey - this is actually the way I followed (without necessarily being fluent in the syntax).

The main report **Overview** is specified like so:

```tjp
navigator navbar {
  hidereport @none
}

macro TaskTip [
  tooltip istask() -8<-
    '''Start: ''' <-query attribute='start'->
    '''End: ''' <-query attribute='end'->
    ----
    '''Resources:'''

    <-query attribute='resources'->
    ----
    '''Precursors: '''

    <-query attribute='precursors'->
    ----
    '''Followers: '''

    <-query attribute='followers'->
    ->8-
]

textreport frame "" {
  header -8<-
    == Toy Software Development Project ==
    <[navigator id="navbar"]>
  ->8-
  footer "----"
  textreport index "Overview" {
    formats html
    center '<[report id="overview"]>'
  }



  textreport development "Development" {
    formats html
    center '<[report id="development"]>'
  }

   textreport "ResourceGraph" {
    formats html
    title "Resource Graph"
    center '<[report id="resourceGraph"]>'
  }
}

taskreport overview "" {
  header -8<-
    === Project Overview ===

    The project is structured into 3 phases.

   
    # <-reportlink id='frame.development'->
  

    === Original Project Plan ===
  ->8-
  columns bsi { title 'WBS' },
          name, start, end, effort, cost,
          revenue, chart { ${TaskTip} }
  # For this report we like to have the abbreviated weekday in front
  # of the date. %a is the tag for this.
  timeformat "%a %Y-%m-%d"
  loadunit days
  hideresource @all
  balance cost rev
  caption 'All effort values are in man days.'

footer -8<-
    === Staffing ===

    All project phases are properly staffed. See [[ResourceGraph]] for
    detailed resource allocations.
  ->8-
}
```

The Report for "Development" is as follows: 
```tjp
taskreport development "" {
  headline "Development - Resource Allocation Report"
  columns bsi { title 'WBS' }, name, start, end, effort { title "Work" },
          duration, chart { ${TaskTip} scale day width 500 }
  timeformat "%Y-%m-%d"
  hideresource ~(isleaf() & isleaf_())
  sortresources name.up
}
```

and finally, the Report for "Resource Graph" is like so: 
```tjp
resourcereport resourceGraph "" {
  headline "Resource Allocation Graph"
  columns no, name, effort, rate, weekly { ${TaskTip} }
  loadunit shortauto
  # We only like to show leaf tasks for leaf resources.
  hidetask ~(isleaf() & isleaf_())
  sorttasks plan.start.up
}
```

Now, save the project definition and compile it:
```shell
tj3 project.tjp
```

after successful scheduling, you'll see a set of HTML files and other assets that have been created. Head over to **Overview.html** in your browser:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/4itzb55kh6ppc2a7x6b7.jpg)

You see **Taskjuggler** has computed a schedule for you. Verify that **precedence** has been respected. Note the cost by task and for the overall project (we have no revenue at this point). Also, see how the **Work** and **Milestones** umbrella tasks make our project schedule clearly presented by separating work to be done and the expected deliveries or milestones.

Let's explore the detailed task description by clicking on the **Development** link:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mespdqr2y2zwtgbmw2kr.jpg)

You see in this Report how tasks are being worked on by each resource.

Now head over to the **Resource Graph** report to see how are resources being used overall in this project:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5ign47qvhefpnskbu0qf.jpg)

You can notice how this report shows how much is every resource being loaded during the execution of its assigned tasks.

# Conclusion
We just scratched the surface of what's possible with **Taskjuggler**. It is really a unique scheduling beast; one that can accomplish so much, but which is unfortunately not well served by its looks.
First, the only viable option to interact with it now is the proprietary syntax we've covered. This is showing its limits, as very poor tooling exists, and for large projects, with complex task hierarchies and report schemes, one can easily feel lost.
Second, although it's possible to track the progress of projects, **Taskjuggler** lacks advanced enterprise collaboration features. I think I've read somewhere it has a server or something, but I don't think it's of any practical use right now.

All of these problems make this tool only fit for the vim-savvy engineer, unfortunately. But once mastered, this is a very sharp one to run accurate time and money estimates, and to effectively track costs, and I think it can perfectly sit next to other collaborative agile Trellos and Jiras.