Package: taskjuggler-python
Unix:Windows:Metrics:Usage:RationaleIt’s[whatever current year]and still most of the tasks/project
management tools lack support for any means of automated planning. This
library helps to integrate automated planner that’s been available for
over a decade, with a shot of suporting different front-ends, complex
scheduling strategies and potentially different planners.Realize your craziest time management dreams!Current focus is on personal planning and small teams (hence no
support for multiple resource yet)No configuration is required to startUtility airtable API example provided with advanced planning strategy
(see below)Overviewpython_taskjugglermodule provides python interfaces to TaskJuggler
3 planner. It is a set of base classes that provide object abstractions
that TaskJuggler internally uses. The module comes with example
implementation of JSON project description parser.It is still work in progress and currently supports:generating taskjuggler project filerunnig the plannerimporting task bookingsworking with single default resource"me"The package comes with an example command line utilitytjp-clientthat provides automatic planning fortasks defined as records inairtabletable.Working with google sheets, jira, trello, todoist, smartsheet and
others could be implemented the same way.The utility allows to immediately re-schedule to reflect any changes to
the plans that may arise due to new fixed appointments, dependencies,
priority amendments or required efforts re-evaluation.Command-line utility usage:$ tjp-client -a airtable -k <airtable_api_key> -b <airtable_database> -t <table_name> -v <view_name>PreparationCreate anairtabledatabase by copyingthis example baseor
create a new database with table named “Tasks” with the following
columns (case sensitive):1. id           - the integer (number) field used as task ID. "Auto Number" type recommended.
2. summary      - single line text: task summary / title
3. effort       - integer number: task effort duration measured in hours. Default value of 1 recommended
4. priority     - single select: field with values "CRITICAL", "High", "Low", "info"
5. preference   - integer number: optional additional number 0-99 for higher granularity of priorities
6. depends      - single line text: with dependencies listed as id's, like: 2,3,4
7. appointment  - date field with time: the fixed tasks or appointments that can not be moved
8. deadline     - date: the desired deadline value. Current strategy will use it to emphasize priority if missed.
9. booking      - date+time: this is where output will be written to. Sort your table by this column

Other columns are just ignored.

You can add nice calculations to the table like time difference between deadline and calculated booking.Create a view calledWorkwith all the tasks with status “Done”
filtered out(it is left as an exercize for the reader to create a
new column and a filter for it)Create a calendar view withbookingfieldAdd some tasks and appointments. Beware not to add impossible
scenarios - those are not supported yet (see console output to check)GetAPI key,database ID, note your table name and view name
should beTasksandWorkrespectivelyExecute in terminal (change base name and key respectively):$tjp-client-aairtable-kkeyAnIuVcuhhkeAkc-bappA8ZtLosVV7HGXy-tTasks-vWorkEnjoy the show oftaskjuggler_pythonmoving your tasks around!Now try changing priorities, adding appointments and re-scheduling the
plan.SetupRequirementsPython 2.7+TaskJuggler 3.6+InstallationInstall TaskJuggler with gem:$geminstalltaskjugglerInstall taskjuggler_python with pip:$pipinstalltaskjuggler_pythonor directly from the source code:$gitclonehttps://github.com/grandrew/taskjuggler-python.git$cdtaskjuggler-python$pythonsetup.pyinstallUsageBasic usage concepts include:ATask, referred to asissuethroughout the codeTask’sidwhich is used to identify and map the tasks - a
property ofJugglerTaskinstanceTask’seffortmeasured in units set asUNITclass
attribute ofJugglerTaskEffortTask’s dependenciesTask’sstartdate (a.k.a. fixed appointment)Task’sprioritymeasured as interger0-1000to set
scheduling preference. No priority is scheduled always first.Bookings - the taskjuggler execution result written asJugglerTask’s property object(s)The minimal invocation will look like:>>>fromtaskjuggler_pythonimportjuggler>>>jg=juggler.GenericJuggler()>>>t=juggler.JugglerTask()>>>t.set_property(juggler.JugglerTaskEffort(1))# hours by default>>>jg.add_task(t)>>>jg.run()>>>t.walk(juggler.JugglerBooking)[0].decode()[datetime.datetime(2017,10,12,13,0,tzinfo=<UTC>),datetime.datetime(2017,10,12,14,0,tzinfo=<UTC>)]JSON tasks loading:$python>>>fromtaskjuggler_pythonimportjsonjuggler>>>my_tasks="""[
  {
    "id": 2,
    "depends": [
      1
    ],
    "allocate": "me",
    "effort": 1.2
  },
  {
    "id": 1,
    "effort": 3,
    "allocate": "me",
    "summary": "test"
  }
]""">>>jg=jsonjuggler.JsonJuggler(my_tasks)>>>jg.run()>>>jg.toJSON()[{"allocate":"me","booking":"2017-10-10T11:00:00+00:00","depends":[1],"effort":1.2,"id":2},{"allocate":"me","booking":"2017-10-10T08:00:00+00:00","effort":3,"id":1,"summary":"test"}]Python interface usage exampleAs an example, let’s create interface to automatically schedule tasks
that are defined as airtable recordsusingAirtable API
wrapper:We are using the fact that airtable’s API already emits nicely
formatted JSON infieldsfield.We only have to name the table columns with correct field names thatjsonjugglerexample wrapper expectsfromairtableimportAirtablefromtaskjuggler_pythonimportjuggler,jsonjugglerairtable=Airtable("appA8ZtLosVV7HGXy","Tasks",api_key="keyAnIuVcuhhkeAkc")# use DictJuggler example wrapper from jsonjuggler module, directly feed what the API emits in "fields"JUGGLER=jsonjuggler.DictJuggler([x["fields"]forxinairtable.get_all(view="Work")])# run taskjuggler and calculate bookingsJUGGLER.run()# walk through all tasks objectsfortinJUGGLER.walk(juggler.JugglerTask):airtable.update_by_field("id",t.get_id(),{"booking":t.walk(juggler.JugglerBooking)[0].decode()[0].isoformat()})# the last line finds first booking in this task, decodes it to datatime list and encodes to isoformatAfter executing this code you should have time assigned to all of your
tasks, none of them overlapping,respecting dependencies, taking into account default time shifts,
appointments and no overwork allowed.Advanced booking strategies exampleImagine that you want your older tasks to increase their percieved
priority so that every task withany priority level gets a chance to be scheduled in the foreseeable
future:# recalculate JSON issue priorities based on deadlinesforrecinjson_issues:if"priority"inrecand"deadline"inrecandnotrec["priority"]>=300:diff_days=(datetime.datetime.now()-dateutil.parser.parse(rec["deadline"])).daysifdiff_days<0:diff_days=0# deny lowering priorityrec["priority"]+=diff_days*3# after 30 days priority is up by 90ifrec["priority"]>=250:# limit maximum percieved priorityrec["priority"]=250#    > 300 is critical in our strategyYou can find the fully working examplehere.Writing your own interfaceSee code for more examples of how to use the interfaces.TODOdocumentation!!TaskJuggler supportgeneral error reporting support (capture stderr and decode id’s)emit warnings if e.g. unable to start appointed event due to slipped
scheduleworking hours, shiftsexporting of tjp file; generating reports, gantt charts, etc.deadline (date) - is a check that the task is not scheduled after
this date [not in planner - this is a check and can not be enforced]task groupinglimits dailymax, etc.fixed stat time/end time (ALAP/ASAP strats)period for appointmentsnon-splittable tasks (X = effort; limits { maximum Xh }??),
split punishingextensive timezone supportmark tasks as done / decouple dependsGeneral enhancementsEnable pylint with configuration that allows the check to pass
(pylint.ini)Loading scheduling resultsexport back to jsonMake ID management transparent in the APIExtensive testing including safe strings checksTaskJuggler task identifier full path, subtask and validationBookings and timesheets supportMonte-carlo simulationsProvide JSONEncoder and JSONDecoder interfaces for jsonjuggler modulehttps://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializableData collection, analytics and prediction (e.g. average task error)Store bookings and do automatic progress analyticsDifferent backend support (e.g. OptaPlanner/Drools; rename topython-plannerpackage?)produce multivariare pareto-optimal solutionsexport to MiniZinc / FlatZinc for generic CP solversGPU-accelerated CP solvers?QCL (Quantum Computation Language) exportThoughtsUse logging to predict average performance per dayCreate a universal API middleware with human interface to help with
life planning and performance measurementsSolve more advanded problemslike “allocate some time during the day to low-priority tasks
if no critical-priority task exist”or “adjust (increase) priority of low-priority tasks according
to their age”Revision History0.0.0 (YYYY/MM/DD)TBD