CrossClj

0.1.4 docs

SourceDocs



RECENT

    automagic-tools-milestones

    Clojars

    Nov 6, 2014


    Readme

    Index of all namespaces


    The README below is fetched from the published project artifact. Some relative links may be broken.

    Milestones - The Thinking Tasks Scheduler

    License GPL 3 Build Status Gratipay Paypal Automagic logo

    “Any sufficiently advanced technology is indistinguishable from magic” - According to Clarke’s 3rd Law

    Milestones is a Clojure library That only needs your project tasks description in order to generate the best possible schedule for you, based on priorities of scheduling you set (in terms of fields in tasks, more about this in a second).

    Constraints on tasks are: - Resource : i.e, which resource is needed to perform task, - The task duration, - And predecessors, i.e, which tasks need to be done before a particular task can be fired.

    Based on the above constraints specification, Milestones generates the Schedule if it does not detect scheduling errors, or shows you th errors.

    Tasks are basically a map containing ids as keys and information about the tasks as values containing maps of task fields pointing to values. Here is an example :

    { 1 { :task-name "A description about this task" 
          :resource-id 2 
          :duration 5 :priority 1}
        
       2 {:task-name "A description about this task" 
          :resource-id 1 
          :duration 4 
          :priority 1 
          :predecessors [1]}}
    

    Milestones tries to detect any circular dependencies, that is, tasks that depend on themselves or on tasks that end up depending on themselves, actually, the tasks definition must be a directed non cyclical graph.

    Tasks (that are not milestones) without resource-ids won’t be scheduled. Those will be reported as erroneous.

    Special tasks with :is-milestone “whatever” are milestones, they are assigned a random user and a duration 1, so they can enter the computation like ordinary tasks. They must have predecessors, else they will be reported as erroneous.

    The output of Milestones is a schedule, that is, if it’s possible, the tasks map, with a :begin field, telling us when to begin each task.

    { 1 { :task-name "A description about this task" 
          :resource-id 2
          :duration 5 
          :priority 1 
          :begin 0}
          
      2 {:task-name "A description about this task" 
         :resource-id 1
         :duration 4 
         :priority 1 
         :predecessors [1] :begin 5}}
    

    Installation

    You can grab it from clojars, using Leiningen, putting the :dependencies in your project.clj: Clojars Project

    Usage

    You fire the library using the schedule function , you pass to it a map containing tasks and a vector containing the properties you want the scheduler to use to give higher priorities to tasks ( less is higher priority) like so (if you want to schedule tasks with lower :priority and lower :duration first)

        (schedule tasks [:priority :duration])
    

    It gives you back tasks with begin fields, or an error

        {:errors nil
        
        :result {1 {**:begin** }}}
    

    Or:

        {:errors {:reordering-errors reordering-errors
                 :tasks-w-predecessors-errors tasks-predecessors-errors
                 :tasks-cycles tasks-cycles
                 :milestones-w-no-predecessors milestones-w-no-predecessors}
                 
         :result nil}
    

    Sample Case

    for example, if you have tasks def’d to:

        { 
        1 {:task-name "Bring bread"
             :resource-id "mehdi"
             :duration 5
             :priority 1
             :predecessors []}
             
        2 {:task-name "Bring butter"
           :resource-id "rafik"
           :duration 5
           :priority 1
           :predecessors []}
        
        3 {:task-name "Put butter on bread"
           :resource-id "salma"
           :duration 3
           :priority 1
           :predecessors [1 2]}
        
        4 {:task-name "Eat toast"
           :resource-id "rafik"
            :duration 4
            :priority 1
            :predecessors [3]}
        
        5 {:task-name "Eat toast"
            :resource-id "salma"
            :duration 4
            :priority 1
            :predecessors [3]}
        
        ;; now some milestones
        6 {:task-name "Toasts ready"
            :is-milestone true
            :predecessors [3]}}
    

    you would want to run

        (schedule tasks [:duration])
    

    and you’d have :

         {:error nil,
          :result {
          ;;tasks with :begin field, i.e at what time shall they be fired.
          1 
          {:achieved 5,
           :begin 1,
           :task-name "Bring bread",
           :resource-id "mehdi",
           :duration 5,
           :priority 1,
           :predecessors []},
          2
          {:achieved 5,
           :begin 1,
           :task-name "Bring butter",
           :resource-id "rafik",
           :duration 5,
           :priority 1,
           :predecessors []},
          3
          {:resource-id "salma",
           :achieved 3,
           :duration 3,
           :predecessors [1 2],
           :begin 6,
           :task-name "Put butter on bread",
           :priority 1},
          4
          {:resource-id "rafik",
           :achieved 4,
           :duration 4,
           :predecessors [3],
           :begin 9,
           :task-name "Eat toast",
           :priority 1},
          5
          {:resource-id "salma",
           :achieved 4,
           :duration 4,
           :predecessors [3],
           :begin 9,
           :task-name "Eat toast",
           :priority 1},
          6
          {:resource-id :milestone-user21667,
           :achieved 1,
           :duration 1,
           :predecessors [3],
           :begin 9,
           :task-name "Toasts ready",
           :is-milestone true}}}
    

    Which you can pass to another program to render as a GANTT diagram (ours is coming soon.) You should have :achieved equal to :duration, or Milestones was not able to schedule all of the task - This should not happen by the way.

    Errors

    Error Map Key What it means
    :reordering-errors { 1 [:priority],…} You gave priority to tasks according to fields (:priority) which some tasks (1) lack)
    :tasks-w-predecessors-errors :{6 [13],…} these tasks have these non-existent predecessors.
    :tasks-w-no-resources [1,… These tasks are no milestones and are not assigned to any resource
    :tasks-cycles [[1 2] [3 5]… Couple of tasks that are in a cycle : 1 depends on 2, and 2 on 1
    :milestones-w-no-predecessors [1 2… These milestones don’t have predecessors

    History

    The concept of auto-magic project scheduling is inspired from the great Taskjuggler..

    A first prototype of Milestones was built as an entry to the Clojure Cup 2014. You can find the code and some technical explanation of the algorithms in use (core.async, etc…) here.

    Although the protorype showcases the main idea, this repository is the official one, i.e, contains latest versions and is more thoroughly tested.

    License and Credits

    Copyright © 2014 Rafik Naccache and Contributors.

    Distributed under the GNU GPL v3.

    All used Libraries in this project (see project.clj) pertain to their respective authors and their respective licenses apply.

    The Automagic Logo - Labeled “The Robot and The Bunny” is created by my friend Chakib Daoud.