How to create a recurrent task?


(Dominique Renauld) #1

I started to use Tinderbox as my new project assistant and it works very well. I don’t regret Omnifocus (which is of course a great tool too). That’s saying something. Little by little, I endeavour to customize that new notebook in such a way as I can integrate it in my daily workflow. These days, I’m trying to figure out how I could create a recurrent task, say: every month, I have to make a back up of some files. What do I have to do to plan that task? Thanks for your help.


A Call for Starter Templates
(eastgate) #2

Let’s say that you mark a task as completed by setting $Checked, and – let’s keep this simple – you have a boolean user attribute $Weekly that means “reschedule this one week after I complete the task.”

An agent could gather all the completed weekly tasks

 Query: $Checked==true & $Weekly == true

and reschedule them

 Action: $Checked=false ; $DueDate=date("today+1 week")

Exercise for the reader: rewrite the action to it will be rescheduled for a week after the task was due, not a week from when it was actually done.

Update: corrected a blunder in the action


(Dominique Renauld) #3

Thank for your answer, Mark. It works, but as soon as the alias quits the container in which the agent gathers it, the $DueDate remains unchanged. But I thought it would change too. Newbie question (please excuse my naivety): does it mean that I have to wait a week before seeing my task rescheduled? My expectation is similar to what I expect from the Today agent $DueDate=="today". Using the Attribute Browser, I can view every task I have to complete today.


(Mark Anderson) #4

I think this should be:

Action: $Checked=false; $DueDate=date("today+1 week")

The ‘&’ is making the action code fail (as & and | joins only make sense in a query). Making the change above, the process works. Don’t forget to allow a short while for the overall turn of the agent cycle. The agent first detects the note and applies the action (cycle #1) and the alias remains until the next cycle (#2) at which point it is removed as it (or rather its original note) no longer matches the query.

Edit: added code style mark-up


(Dominique Renauld) #5

Thank you Mark. It works very well. With this last feature, I can say I have a complete project assistant and more, seeing as all the things I can do with Tinderbox, from brainstorming or concept-mapping a project to “timelining” an entire project.


(eastgate) #6

For latecomers, I’d like to highlight a subtlety above that is, I think, a nice example of the flexibility of Tinderbox.

THE PROBLEM: We want recurring tasks – tasks that reschedule themselves after they’ve been performed. But we might conceivably want either of two different policies:

  • Reschedule the task one week from the time is was originally scheduled (e.g. “every Wednesday”)
  • Reschedule the task one week from the time you did it (e.g. “practice the sonata once a week”)

Lots of programs would assume one policy or the other. Some might let you select which one you prefer, at the cost of complicating the user interface.

Tinderbox can let you use either, and also let you inherit which policy makes sense from the prototype task. So, the meeting of the Planning Committee is an instance of Meeting, assumes that meetings will be held at fixed intervals, and installs the appropriate default rule. If this is a special case and needs its own rule, though, you can write a special rule just for the Planning Committee.


(Pat Maddox) #7

I’m back on OmniFocus for task management, but one thing I found really helpful when using Tinderbox was prototypes with children.

I set up a single “Today” prototype that looked like:

  • Today
    • Monday
      • take out trash
    • Tuesday
      • bring in trash
    • walk dogs
    • feed dogs
    • pick up yard

Those cover my daily / weekly recurring tasks… each day I’d make a new note, set the prototype to “Today”, and then delete any days that weren’t relevant. Then I’d add any specific tasks to today’s list.

Maybe the agent-style date resetting works better for you in this case, but I was a big fan of prototypes with children to automatically create a note structure.


(Mark Ware) #8

The behaviour I’d like is to automatically create a duplicate of the completed task with $Checked=false & DueDate set for the new date. That way I’d get to keep a record of the completed task in my Archive.

Is this possible with Tinderbox? I think I read somewhere that agents can’t create new notes, though?


(eastgate) #9

Tinderbox actions cannot create new notes.

But you can arrange for your manually-created new note (or duplicated note) to do whatever you want to do.


(Les Sebba) #10

Newbie Question related to the recurring date question above. I am trying to use the Timeline view to keep track of upcoming meetings. Many of my meetings occur on a recurring basis such as the 4th Tuesday of every month. Let’s assume I use $EndDate for the meeting date. Is there a way to create an action that updates the $EndDate to the next month once the current meeting date is past?

Thanks


(Mark Anderson) #11

Yes - via action code (and more here). You could use a rule or an edict. Given the periodicity, I’d suggest an edict. Also, as you’ll likely have several such notes I’d suggest they all use a prototype (and the same one!). That way you’ll write your action once in the prototype and it will be inherited/used by all the notes using that prototype.

So, we test if $EndDate is older than today (i.e. the current system date/time):

if($EndDate < date("today"))

The other task is if the test passes, and only if, we then set $EndDate forward one month:

$EndDate = date($EndDate + "1 month");

Wrapping that up as a complete action, I’d suggest your edict be:

if($EndDate < date("today")){
   $EndDate = date($EndDate + "1 month");
};

I’ve put line breaks for clarity. In shorter typed form, as when typed into the Edict Inspector, it can just as easily be:

if($EndDate < date("today")){$EndDate = date($EndDate + "1 month");};

Further relevant articles/tutorials:


(Les Sebba) #12

Thank you. I find it so much easier to learn when a specific example is spelled out this way.

However, the problem is the “1 month”. So if for example, the meeting occurs on the 4th Tuesday of every month, adding 1 month does not solve the problem. For example, if the meeting occurred on Tues July 24, adding one month gives an output of Aug 24, when the 4th Tues of August is the 28th. It does not work to add 1 month, nor does it work to add 4 weeks, since it depends on the number of days in the month, and which day of the week is the 1st day of the month. I think I need an expression, in this example that is able to find the 1st Tuesday of the following month and then add 21 days to it. That is where I am stuck.

Thanks for your help


(James Fallows) #13

My guess (not being a programmer) is that this is the kind of low-frequency chore where the time and effort required to automate it might be much greater than the time required just to do the fine-tuning manually. That is:

  • If you did this in a rough-and-ready way, you could automate the monthly updating of $EndDate, by using the code shown above: $EndDate = date($EndDate + "1 month") That would move you 30 days forward, into the next month.
    THEN, you could eyeball the new date and adjust it up or down a few days as needed. The automation in this case would be rolling things over to the next month, and the manual tuning would be setting the specific date.

  • Or, if you wanted to automate things fully, you could put together some if / else conditions to (a) search for the first day of the following month, then (b) search for the Tuesday after that, then ( c) specify 21 days after that. I am sure this is doable within Tinderbox, but it would take some patience in setting things up the right way.
    If you were going to run this function thousands of times, it would be worth figuring out that code. If it’s just a few times per month, I’d take the rough-and-ready approach above. (And the right approach for you is whether you’d look on the additional coding steps as enjoyable puzzle-solving or a chore.)


(Mark Anderson) #14

Ah, I’d overlooked the specificity of that request. Dates and calendaring can be rather complex. I don’t believe (happy to be wrong) the Tinderbox has such specialist tools. You might do better to look at adding a command line call to a script or tool had can return the new date. But, try this edict:

if($EndDate < date("today")){
   $MyDate = date($EndDate+"1 month");
   var newYear($MyDate.year);
   var newMonth($MyDate.month);
   $MyDate.day = runCommand("cal -h "+newMonth+" "+newYear+" | awk '{print substr($0, 7, 2)}' | grep [0-9] | head -4 | tail -1");
   $EndDate = $MyDate;
   $MyDate=;
};

(Mark Anderson) #15

As this is using runCommand and you don’t want to be constantly polling the command line, I’d definitely run this as an edict.


(Les Sebba) #16

You are 100% correct. Sadly, I fall into the category of “Can I solve this puzzle challenge?”. So I will probably end up spending much more time than it is worth on this.


(eastgate) #17

First: it might be a mistake to use Tinderbox to replace your calendar program. iCal and BusyCal and the rest do a wonderful job at keeping track of dates; it’s what they do. I’ve written more about this in The Tinderbox Way: it’s often better to use calendars for your calendar and Tinderbox for your notes.

Still, you can do likely do what you want without too much fuss. Suppose today is Tuesday, July 4.

Next month (Aug 4): date($EndDate+" 1 month")
Four weeks later: date($EndDate+" 4 weeks")
First Tuesday in August: this is only a little bit tricker.

First, we look four weeks ahead:

$MyDate=date($EndDate+" 4 weeks");

If that’s in August, we’re done.

if ($MyDate.month!=$EndDate.month) {$EndDate=$MyDate;} else {…

But if 4 weeks later leaves us still in July, we want to add another week.

if ($MyDate.month!=$EndDate.month) {$EndDate=$MyDate;} else {$EndDate=$MyDate+} 7 days"};

So that’s a little more work than might be ideal, but it’s not that bad.


(Les Sebba) #18

Thanks very much. This is very helpful


(James Fallows) #19

Thanks for raising this question, and to the assembled gurus here for their answers. The value of these “in public” questions is that, even for people (like me) who are not dealing with the specific task you’re asking about, the answers shed light on other ways to use the software. Thanks all.


(Les Sebba) #20

Since I have no knowledge of scripting, I was unable to take Mark’s scirpt and use it for other days, dates. So I looked a a calendar to figure out the logic on how to get to from the 4th (or 3rd or 2nd) (Mon)(Tues)day to the same day and week in the following month. I’ll try to spell out my solution in case anyone else needs it at some point. Please excuse my rudimentary construction of the action as I am still learning my way around.

The challenge is that there may be 4 or 5 occurrences of any particular day in a month. So if we take Tues in Wed in July there are 5 Tuesday and 4 Wednesdays. Therefore to get from the 3rd Tues in July to the 3rd Tues in Aug entails 5 weeks, not 4 as in the 3rd Wed.

My solution was to take the meeting date ($EndDate), and make $MyDate = $EndDate+21 days. This $MyDate to the 1st Tuesday and second Wed. I used var x = day(theDate) in an if statement. If it returned a number > 7, it means that $MyDate is on the second occurrence of the weekday, and I used day(theDate, value) to change the value to x-7. This results in $MyDate having a value that returns the first occurrence of the weekday, and adding 14 days ensures that $EndDate = $MyDate = the correct occurrence. An agent adjusted for the appropriate interval for each week can make this routine work for any week or weekday.

Query:$EndDate<date(“today”) & $Prototype==“recurwk3”

Action:

var x; var z; var a; $MyDate=$EndDate + “21 days”; x = day($MyDate); z=x-7; a = z + 14;
if (x>7) {$MyDate=day($MyDate,a);$EndDate=$MyDate;}
else{$EndDate=$MyDate + “14 days”};
$MyDate=;

Question: day(theDate, value) seems only take a value for the “value” component. An expression such as . x-7 does not seem to work. Is this correct?