Sunteți pe pagina 1din 67

Tinderbox Actions

and Dashboards
Mark Bernstein

© Copyright 2015 by Eastgate Systems, Inc. All Rights Reserved.

Tinderbox™ is a trademark of Eastgate Systems, Inc. All other trademarks herein are used illustratively and are
the property of their respective owners.

The story and example expense account data used here is a work of fiction. All persons, places, and institutions
mentioned therein are imaginary, and any resemblance to actual places, institutions, or persons alive or dead, is
entirely coincidental.
1
Table of Contents

1. Actions and Dashboards 2


2. A Look At The Data 6
3. Collecting Notes with Agents 12
4. Summarizing Agent Information With Display Expressions 23
5. Summarizing Agent Information With Dashboard Notes 33
6. Actions For Automating Routine Chores 40
7. Progress Bars 47
8. Seeing The Data 55
9. Treemaps 60
2

1. Actions and Dashboards


Tinderbox is the tool for notes, a unique and powerful approach to
visualizing, organizing, and sharing information about complex problems.
Tinderbox makes it easy to make notes, even for ambitious and complex
projects that may last for months or years and may take unexpected twists
and turns. Tinderbox can actively work with you, taking actions to help keep
your notes organized and to help you visualize and understand them.
If you’d like to know more about the design of Tinderbox and why it behaves
as it does, you may enjoy The Tinderbox Way, a book about Tinderbox that is
published by Eastgate. (order here)

You don’t need to read this


There are lots of ways to use Tinderbox. The approach here is not the only or
the best way to use Tinderbox. As you use Tinderbox, you will notice many
alternate ways to do things; don’t assume the method used here is the best
for you.
3
If you’re just getting started with Tinderbox, you might want to read some of
Getting Started With Tinderbox first. You’ll find that tutorial in the Tinderbox
Help menu.
Actions can help reduce boring and routine chores, freeing you to
concentrate on matters that do require your full attention. They can help
avoid mistakes and oversights, such as filling in dates or copying routine
metadata. Not every Tinderbox project requires lots of actions. If you find it
easier to do something yourself, there may be no reason to have Tinderbox
do it for you.

Things Change
This tutorial was originally written for Tinderbox 6.3. New versions of
Tinderbox appear frequently, and the version you’re using is probably newer.
Nearly 100 official Tinderbox versions have already been released to
customers, and updates arrive frequently.
Details of the sample document may have changed since the screen shots in
this tutorial were captured, and as a result some of the results will differ
numerically from those illustrated here.
4
Some details discussed here may vary from the version of the program you
are using. Don’t worry too much: the underlying principles and concepts still
apply. If you’re stuck, feel free to ask on the Tinderbox Forum, or email
Eastgate.

The Problem
In this tutorial, we’ll explore and analyze some expenses incurred during a
fictional business trip. The sample data and analytical tools can be found in a
Tinderbox document you can download from:
http://www.eastgate.com/download/ActionsAndDashboards.dmg
In this tutorial, we explore some ways we can use Tinderbox to automate,
analyze, and visualize this rather mundane information. Realistically, you
would be unlikely to want to invest this much care in such mundane and
manageable data, but the same techniques can be applied to your own,
subtler problems.
Suspend your disbelief: If you’re confronting problems that don’t seem
analogous to those described here, Tinderbox might still be able to help.
5
Again, ask in the Tinderbox forum, where lots of Tinderbox users welcome
such questions, or email Eastgate.

Other Resources
Other places to find information about Tinderbox include:
Tinderbox Help, a detailed manual found in the Help menu.

Getting Started With Tinderbox, a tutorial found in the Help menu.

The Tinderbox Forum, http://eastgate.com/Tinderbox/forum/, is an active and friendly


meeting place for active Tinderbox users from a wide range of fields.

aTbRef – a Tinderbox Reference – is a technical reference for Tinderbox written by


Tinderbox user Mark Anderson and available both as a web site and a Tinderbox
document at http://www.acrobatfaq.com/atbref6/ .

Mark Bernstein’s book The Tinderbox Way discusses the core ideas that underlie
Tinderbox. It is available as an eBook from Eastgate.

6

2. A Look At The Data


Lise Nakamura is Vice President of Design at TK Corporation. an
international technology company that creates tools to help parents keep
track of what their children are doing1. In an increasingly complex and
mobile world, TK’s products have been wildly successful and the underlying
technology has found spinoff opportunities in fields ranging from warehouse
management to law enforcement.
On April 24, the weekly meeting of the Executive Planning Committee
discussed repeated delays and performance issues with the overseas supply
chain for the company’s crucial new product, slated to be announced in a
mere four months. The natural person to look into these problems is Don
Frost, VP of Operations and Nakamura’s supervisor. Unfortunately, Frost is
not available until April 28: he is recently divorced and his daughter is
competing in an invitational tournament in Chicago this weekend. CEO Ken
Biggs is reluctant to wait, and the committee agrees that Nakamura will
leave for the Paris office on the first available flight.

1 All the people, places, and institutions mentioned here are fictitious, or are used fictitiously.
7
Over the course of the following weeks, Nakamura visits a number of cities
across Europe and North Africa, meeting with TK personnel, contractors,
vendors, government officials, heads of charitable foundations and other
stakeholders in order to understand the causes for these problems.
The first, leftmost tab in the example Tinderbox document is simply a list of
expenses incurred during this trip.
8

This list contains three kinds of notes. Each type of note has its own
prototype and appearance:
1. City notes are containers for each major stop in Nakamura’s trip. Their
titles are bold.
2. Summary notes briefly outline each day’s business, both for mandatory
record-keeping and to provide context to the Account Department when
they come to authorize reimbursement. Their titles use the Sketchnote
font.
3. Expense notes describe one expenditure, explaining who was paid, how
the payment was made, and occasionally providing additional detail for
the benefit of the Accounting or Legal departments. Their titles use plain
font.

Prototypes
Click on the Prototypes tab to see the prototypes used in this document. In
the upper right-hand corner of the map, the adornment named Data
Prototypes contains prototypes used to characterize these expenses:
9
City

Summary

Draft Summary

Expense

The prototype defines what sort of note each note is. Every expense record
adopts Expense as its prototype, so it’s easy to find expenses and separate
them from other notes.
Second, the prototype defines the base appearance of each note. The
distinctive font and color the Summary notes and the bold font of City notes
are inherited from the prototype; we don’t need to remember to set these
manually, and have no worries about
accidental inconsistencies.
Third, each prototype defines some key
attributes that are particularly relevant to
notes of that type.
• City simply records the $Currency typically
used in that place and the $StartDate of our visit to that city.
• Summary uses $StartDate to record the day it summarizes.
10
• Each Expense records a list of information about a single expenditure.
$StartDate is the date of payment, and $City is the place where the
payment was made. $Recipient is a user
attribute where we record whom we paid.
We record the $Amount we paid, the
$Currency we used, and the equivalent of
this payment in US $Dollars2. $Method
records whether the recipient was paid in
cash or credit card. Finally, $Tags holds a
set of tags that will help us (and the
Accounting Department) categorize and account for each expense. Tags
might include “lodging”, “travel”, “meals” (with additional tags such as
“lunch” and “dinner”), as well as tags about client accounts or projects
associated with the expense.
Every expense needs to record this information. It does us little good, for
example, to know that we spent 46.50 on dinner in Zürich if we forget to

2 Later, we will arrange this Tinderbox document so it automatically performs the currency conversions for us, and fills out many of
these fields automatically. If we expect to have only a few expenses over a short period of time, we could simply fill these out
manually; if we will be using this project daily for months or years, we might eventually decide to automate some of the more tedious
or error-prone chores as we have done in this example.
11
record whether we paid in Euros or Dollars or Swiss Francs. The list of key
attributes helps ensure that we will capture the information we need.
☞ Resist the temptation to add unnecessary key attributes. When you are in a hurry, you’ll
be tempted to skip over them or to add the data later, but questions that can be answered
today with ease may prove nettlesome to recall next week, or the night before the expense
report is due.
12

3. Collecting Notes with Agents


Tinderbox agents constantly scan your document, looking for notes that
match their specific criteria. When an agent finds a note that satisfies the
agent’s query, it creates an alias of that note inside the agent. The agent may
perform an action on the matching note. Finally, the agent may sort the
aliases it has gathered.
In this chapter, we will focus on agent queries – on the ways agents look for
notes that interest us.
To begin, open your copy of the Expense Account sample document and
select the tab labeled “Sandbox”. This container holds a number of simple
agents discussed below. As you read, feel free to add your own agents to this
container.

Collecting Expenses
The first agent in the Sandbox is named All Expenses, and collects every
note that uses the Expense prototype. In outline view, click on All Expenses
to select it, and click on its disclosure triangle to expand it. Inside the agent,
13
you will see a long list of aliases, one
for each expense recorded in the
entire document.
With All Expenses selected, open
the Inspector by choosing Inspector
from the Windows menu. Select the
Action Inspector, marked with a ⚙
icon, and choose the Query pane.
This Query is simply a logical
expression which is applied in turn
to every note; if the result is true, the
note’s alias is gathered by the agent,
while if the result is false the agent
takes no further action on that note.
Agent:"All"Expenses

Query:"$Prototype=="Expense""
14
The unusual operator “==” is the comparison operator, and is true if two things are equal.
We use it here to avoid confusion with the assignment operator “=”, which sets the value
of an attribute.

Note that, in the right-hand corner of this pane, Tinderbox displays the
number of notes currently found by this agent.

Sorting Expenses
Next, switch to the Sort pane of the
Action Inspector. Here, we choose
how the aliases inside the agent
should be arranged. Initially, they
are sorted using the system attribute
$StartDate, in the Event category.
The expenses are arranged in
chronological order, with the first
expenses – lunch at the airport and a
Paris guidebook – at the top and the
latest expenses at the bottom.
We can easily choose different
15
sorting criteria. Be sure that All Expenses is still selected, and click on the
Sort By pulldown menu and select Dollars from the User category, near the
top of the menu. The list is now sorted by expense, starting with a $4.99
downloadable map. Click on the reverse checkbox to invert the sort order;
now, the first item is our costly same-day flight from Boston to Paris.
For convenience, collapse the outline disclosure triangle of All Expenses
before continuing.

Keeping An Eye On Agents


The Agents and Rules pane of the
Tinderbox Inspector provides useful
information on what your agents are
doing from moment to moment.
The upper bar in this inspector is our
chief interest here. We can see at a
glance how many agents this
document contains, and that
Tinderbox is currently working on
the agent named “meals”. The blue
16
marker gradually moves from left to right as Tinderbox runs agents from the
start of your document to its end, and you can judge from its progress how
much time it takes for Tinderbox to bring all your agents up to date.

Collecting Specific Expenses


We might use agents to examine some specific expense categories. For
example, the agent Meals gathers all expenses relating to meals.
Agent:++++Meals

Query:""""$Prototype=="Expense""&"$Tags.contains("meal")

Sort:"""""$StartDate+

To qualify for this agent, a note must be an expense and it must have the tag
“meal.” The ampersand (&) is the logical “and” operator; the query is true if
its left side is true and its right side is also true.
$Tags is a set attribute – a list of labels or “tags,” separated by semicolons.
The expression
$Tags.contains("meal")"

is true if one of the elements in $Tags is “meal”.


17
Tinderbox knows that if the left side of the & is false, the result must be false and that
there is no need for further work. Knowing this can sometimes make your agents more
efficient.

Again, view the query and sort in the inspector, and expand the agent in
outline view to see which notes it has gathered. It’s always a good idea to
examine what your agents find!

Collecting Major Expenses


We might require special authorization for certain expenses. The agent
Authorization Required looks for all expenses over $1000, and also for all
cash expenditures of any amount.
Agent:"Authorization"Required

"
Query:"inside(/Examples/All"Expenses)"&"($Dollars>1000"|"$Method="cash")"
"

The first clause is true for all notes that are inside the agent All Expenses
inside the container Examples. In this case, we might equivalently have
written
$Prototype=="Expense""
18
but if All Expenses required lots of computing work to finds its results,
inside() lets other agents take advantage of that work without having to
replicate it.
The second clause
($Dollars>1000"|"$Method=="cash")"

is contained in parentheses because we want its result to be true if either the


cost exceeded the $1000 threshold of if the payment was made in cash. The
“|” symbol is the logical “or” operator, and is true if either its left clause is
true or if its right-clause is true.

Weekends, Only
Because a proposed cost-control initiative advocates minimizing business
travel over weekends, we might need to identify expenditures on Saturdays
and Sundays.
Agent:""
Weekends"Only

Query:""
$Prototype=="Expense""&"("$StartDate.weekday==6|$StartDate.weekday==7")

Sort:"
""$StartDate" "

The .weekday facet of date attributes returns the weekday as a number,


where “1” corresponds to Monday and “7” corresponds to Sunday. We sort
19
this agent’s results by $StartDate for clarity, so expenses from our first
weekend abroad aren’t mixed with expenses from our second weekend.

May Day
We might want to locate all expenses from a specific date.
Agent:""
May"Day

Query:""
$Prototype=="Expense""&"$StartDate==date("5/1/2015"")"

Sort:"
""$StartDate" "

This is simple enough, but does raise a few tricky issues concerning dates.
First, the date() operator converts strings to dates. The string can be any
date that Tinderbox recognizes, including dates expressed in your
computer’s local date preferences. If we were using a computer configured
with British date preferences (in System Preferences:Language and Region),
we’d write “1/5/2015” in conformance with British usage. Alternatively, we
could write “May 1, 2015” in either in the US or 1 May 2015 in the UK.
Second, Tinderbox dates always include a time of day. By convention, the
equality operator == is true if two dates fall on the same calendar day. If
event A begins on Monday morning and event B begins on Monday
20
afternoon, then $StartDate(A) == $StartDate(B) is true, even though
$StartDate(A)<$StartDate(B) is also true3.

Making A Timeline
Lise Nakamura’s trip is long and complicated, and the Accounting
Department might find it a bit confusing. A timeline can help sort things out.

Zürich Vienna Gothenburg Boston

Boston near Como Marrakesh Stavanger (by car)

Paris Torino

London:
WatchfulCon

Dijon Tel Aviv

4/26/2015 5/3/2015 5/10/2015 5/17/2015

3 All Tinderbox date attributes record a moment in time, including the time of day. When people ask whether two dates are equal,
though, they most often want to know if they refer to the same calendar day, not the same second.
21
We begin by making an agent to gather all the City notes.
Agent:+All"Cities

+
Query:+$Prototype=="City""
+

Next, we’ll focus the view to focus only on the results of this agent. Select
All Cities and choose Focus View
from the View menu. Finally,
choose Timeline from the View
menu. We see a simple timeline of
the cities visited in the course of this
trip.
To return to the outline view, choose
Outline from the View menu and
then click on Sandbox in the
breadcrumb bar to expand the view
to the Sandbox container.

Mistakes: Finding Missing Tags


We use $Tags to assign each expenditure to one or more categories, so the
Accounting Department can handle each expense appropriately. Common
22
tags include “entertainment”, “transportation”, “lodging”, and “meals”.
Meals are also tagged with “breakfast”, “lunch” or “dinner” where
appropriate. Tags might indicate particular colleagues or customers whose
bill was paid, accounts that might be charged for the expense, and other
short memoranda.
In the rush of work, we might forget to tag an expense; an agent can easily
find any expenses without tags.
Agent:""
No"Tags"
Query:""
$Prototype=="Expense""&"$Tags=="""

Only slightly more work is required to locate expenses for meals that aren’t
tagged with a particular meal.
Agent:""
No"Meal"
Query:""
$Prototype=="Expense""&"$Tags.contains("meal")"

&"!($Tags.contains("breakfast")|"$Tags.contains("lunch")"|"
$Tags.contains("dinner")")"

The “!” operator is the “not” operator: if what follows it is true, is returns
false.
23

4. Summarizing Agent Information With


Display Expressions
The agent queries we created in the
previous section are expressions –
values or combinations of values.
Another use for expressions is the
note’s Display Expression, a formula
Tinderbox uses to determine how
each note should be labelled4. Each
note can have its own Display
Expression, stored in its attribute
$DisplayExpression.
The Title pane of the Text inspector
lets you inspect and change display
expressions. Simply type the Display
Expression in the appropriate text
box and press [Return].
4 If a note has no $DisplayExpression, Tinderbox displays that value of the note’s $Name.
24
☞The Display Expression is a formula, a recipe for constructing the name. Don’t confuse
the expression with its result. Several notes might have the identical expression but, since
the notes are different, they would display different results.

Counting Notes
The first agent we created in the Sandbox container collected every Expense
in the document.
Agent:"All"Expenses

Query:"$Prototype=="Expense""

To keep track of the total number of


expenses in the document, we could set
up this agent to display the number of
expenses it found in its title.
DisplayExpression:"$Name+":""+$ChildCount"

When applied to strings like $Name, the “+” operator joins two strings
together. Thus, Tinderbox starts with the note’s $Name, appends a colon,
and then appends the number of children inside the agent.
Alternatively, we might write
DisplayExpression:"$ChildCount+""Expenses""
25
to label the agent “55 Expenses.”

Total Expense
Rather than reporting the number of expenses, we might be interested in the
cumulative total. Rather than change the agent All Expenses again, we’ll
define a new agent.
Agent:"Total

Query:"inside(/Sandbox/All"Expenses)

"
Display+Expression:"$Name+":""+sum(children,$Dollars)"

The query simply matches all notes that the agent named “All Expenses” has
found; this is a convenient shortcut that lets agents work together without
duplicating work.
The display expression adds up the value of $Dollars for all the agent’s
children, and appends the result to the agent’s name. This will display the
total as a number.
Total: 11955.3
Since we know the result is expressed in our local currency, we might format
it more suitably:
Display+Expression:"$Name+":""+sum(children,$Dollars).format("$")"
26
This takes the number
sum(children,$Dollars)"

and asks Tinderbox to format it


[Number].format(format'string)+

The “$” argument to format means “format this number according to the
computer’s local currency formatting.” The result will look something like
this:
Total: $11,955.30
The currency symbol and conventions for punctuating currency are based on
the locale you choose in System Preferences: Language & Region.

First and Last Notes


Instead of knowing the total, we might want our agent to tell us about the
dates covered in its list of expenses.
Agent:"Range

Query:"inside(/Sandbox/All"Expenses)

"
Sort:"
""StartDate

Display+Expression:"$Name+":""+$StartDate(child).format("l")"
27
We sort the agent to ensure that the first child is the earliest expense. The
“l” argument to the format() operator formats the date using your locale’s
short date format. In the US, the result should look something like this:
Range: 4/28/15
Elsewhere, the date will be formatted according to your system settings
We might display the latest expense, too, changing the display expression to
$Name+":""+$StartDate(child).format("l")+"\"+$StartDate(lastChild).format("l")"

The result will now look something like:


Range: 4/28/15 - 5/7/15
Of course, the actual results might differ depending on your system’s
language and format settings.

Taking The Average, Finding The Range


Perhaps we need the average dinner bill.
Agent:"Dinners

Query:"inside(/Sandbox/All"Expenses)&$Tags.contains("dinner")

"
Sort:"
""StartDate

Display+Expression:"$Name+":""+avg(children,$Dollars).format("l")"
28
Alternatively, we might be interested in the largest and the smallest dinner
expenses. Let’s construct the display expression step by step; this is usually
the best approach to building a complex expression.
We begin very simply.
Display+Expression:"$Name+":"""

This displays:
Dinners:
The min and max operators require a list of values. We can create a list using
the collect() function.
Display+Expression:"$Name+":""+collect(children,$Dollars)"

This displays a list of dinner bills separated by semicolons:


Dinners: 153.36;223.65;45.36;46.44;34.56;248.83 ….
Tinderbox has gone through each of the agent’s children, collected its value
of $Dollars, and appended it to this list. To find the smallest bill, we pass the
list to min():
Display+Expression:"$Name+":""+min(collect(children,$Dollars))"

This displays something like:


29
Dinners: 20.8
As before, we’ll format the result as currency.
Display+Expression:"$Name+":""+min(collect(children,$Dollars)).format("$")"

which displays:
Dinners: $20.80
Finally, we’ll add a dash and then find the largest dinner bill:

Display+Expression:"$Name+":""+"min(collect(children,$Dollars)).format("$")

+""–"""+"max(collect(children,$Dollars)).format("$")"

Which displays something like


Dinners: $20.80 – $248.83
30
Incrementally building and testing complex expressions lets you refine your
work in small and simple steps and helps identify mistakes at once

Summary Tables
In maps, when an agent has located some notes, we
typically see those notes inside the agent.
Sometimes, it’s more informative to list those notes
by name, perhaps appending some additional
columns of information we want to see. We can add
a summary table to any container or agent to do this.
For example, select the tab names Status and locate
the agent “missing tags”. This agent looks for any Expense reports that have
no tags; because every expense should have some category or explanation,
31
we’ll need to locate any unexplained expenses before submitting our report
to the Accounting Department.
We can inspect the agent’s query by selecting
it and opening the action inspector. The agent
looks through the entire document and finds
notes that use Expense as a prototype but that
have no tags.
The summary table is drawn in the agent’s
title bar below the agent’s name, provided
there’s sufficient space. To give us room to
display the table, select the agent and then
drag the top of the title bar upward, so the
title bar fills the agent.
Next, click on the Summary Table widget, marked
here with a blue arrow. Each column in the summary
table is listed in turn: here, we have only a single
column which lists the note’s name. We could add
additional columns here if we wished. Click
32
anywhere outside the Summary Table Properties popover to dismiss it.
As downloaded, the sample file has no
untagged expenses and so the summary
table is empty. Double-click the map
background to create a new note, name
it “test expense”, and use the note’s
prototype tab to select the Prototype
“Expense”. After a few seconds, the
note will appear in the summary table.
☞You may choose File ▸ Update Agents
Now to ask Tinderbox to update all
agents right away.
33

5. Summarizing Agent Information With


Dashboard Notes
Display expressions work well if we want to extract one key aspect of an
agent, provided that we remember to look at the agent. Sometimes, we might
want to display several aspects of an agent, or of several agents that might be
scattered throughout your document.
A Tinderbox dashboard is simply a collection of notes that display summary
information of interest in a single convenient place. The expense account
sample file includes a dashboard container named Status. Click on its map
view tab for an overview of the entire document.

A Dashboard Note
The left-hand side of this dashboard has several notes that use the prototype
Dashboard for a distinctive appearance. The Dashboard prototype is located
in the Prototypes folder, and has the following properties:
Color: “3” (matching the background color)

BorderColor: transparent
34
BorderStyle: plain

Shadow: false

SubtitleSize: 75

SubtitleColor: green5

Using the Inspector to set all these parameters for each dashboard note
could be tedious, but prototypes lets notes inherit all these characteristics in
one step, and also let you modify the appearance of all dashboard notes by
changing the prototype.

Counting Notes: Subtitle


We begin with the note “transactions,” which counts the total number of
expenses found in the entire document. This note has a Rule:
Name:&
&&transactions

Rule:&
&&$Subtitle=$ChildCount(/Infrastructure/all&expenses)&

This rule asks Tinderbox to locate the child count of another note — an
agent named “all expenses” inside a container named “Infrastructure” – and
then to store the result in this note’s subtitle.

5 The color “green” in this document has been defined as #5e8663 — a neutral gray-green.
35
Tinderbox constantly evaluates rules, running the rules for each note until it
reaches the end of the document and then starting over at the document’s
beginning6.

Getting The Total


In the upper left-hand corner of the dashboard, we see a
note named “total cost” that adds up the cost of every
expense in the document. Again, we construct a rule
which finds the total cost and stores that cost in Subtitle.
Let’s consider how we might write this rule in small and
simple steps.
Name:&total&cost

Rule:&$Subtitle=42&

6A second kind of rule, called an Edict, is run less frequently than regular rules and is useful when the result of a rule will seldom
change.
36
This is very simple indeed — it takes the number “42” and stores it in
$Subtitle. Once the rule runs, this dummy value will appear in the dashboard.
(You may need to deselect the note to allow the screen to update.)
We’d like the subtitle to be formatted as currency.
Name:&total&cost

Rule:&$Subtitle=42.format("$")&

Finally, we replace the dummy value with the real value.


We’ll look inside the container named Expense Account and total up all the
dollars expended:
Name:&total&cost

Rule:&$Subtitle=sum(descendants(/Expense&Account),$Dollars).format("$")&
37

The Places We’ve Been


Each expense entry records the city where the expense was incurred. How
many cities have we visited?
First, we need a list of all the expenses. The expression
find(Prototype=="Expense")&

builds exactly this list, returning the $Path for each note that uses "Expense"
as its prototype. Next, we find the value of $City for each expense:
collect(find($Prototype="Expense"),&+$City)+

Once we have the list of cities, we remove all any duplicates:


collect(find($Prototype="Expense"),&&$City).unique&

and, to wrap everything up, we get the size of the remaining list
collect(find($Prototype="Expense"),&&$City).unique.size+

So, our dashboard note is:


Name:&cities

Rule:&$Subtitle=collect(find($Prototype="Expense"),$City).unique.size&&
38

First and Last


What is the earliest expense associated with this trip? We already have an
agent /Infrastructure/all expenses that locates every expense record. It
keeps the expenses sorted by date, so the earliest expense will be that agent’s
first child.
$StartDate(child(/Infrastructure/all&expenses))&

The latest date, conversely, would be


$StartDate(lastChild(/Infrastructure/all&expenses))&

For convenience, we can store this data in the $StartDate of this


dashboard note.
$StartDate=$StartDate(child(/Infrastructure/all&expenses))&

Finally, we format the date and store the result in the dashboard
note’s subtitle.
Name:&start

Rule:&$StartDate=$StartDate(child(/Infrastructure/all&expenses));

$Subtitle=$StartDate.format("m/d")&
39
How long have we been away? Our start date is now conveniently available
as
$StarDate(/Status/start)&

and our end date is simply


$StarDate(/Status/end)&

so we can very easily write a note that reports how long we’ve
been away from the office.
Name:&days

Rule:&$Subtitle=days($StartDate(/Status/start),&$StartDate(/Status/end))

40

6. Actions For Automating Routine Chores


In the previous chapter, we used rules to manipulate and move data to some
dashboard notes. Now, we turn to actions that help keep your information
organized, consistent, and up to date.
Tinderbox provides four kinds of actions:
• Rules are actions that are applied periodically to a single note
• Edicts are like rules, but are performed less frequently
• Agent actions are applied to notes that match the agent’s query
• OnAdd actions are applied when notes are added to a container or are
placed atop an adornment

Keeping Your Data Consistent


We use the $Tags field, a set attribute, to annotate each expense with
information about purpose and context. In many cases, the Accounting
Department requires tags to process each expense and to apply the charge to
the appropriate account. Other tags are for our own convenience, so we can
more readily relocate various kinds of expenses.
41
For example, all expenses related to transportation should be tagged with
“transportation” and also with the kind of transport: plane, train, rented car,
taxi, and so forth. If we’re in a hurry or distracted, we might omit one of
these tags.
Click on the Infrastructure tab to view an outline of the Infrastructure
container. There you will find an agent named “taxis” that looks for notes
whose title contains the letters “taxi” or that are tagged with “taxi”.
Name:&&&&&taxis&
Query:&&&&inside(/Infrastructure/all&expenses)&&&($Name.contains("taxi")|
$Tags.contains("taxi"))&
Action:+++$Tags=$Tags+"taxi;transportation"&

The action makes adds the tags “transportation” and “taxi” to the tags of
any expense the agent finds. Since $Tags is a set, duplicate tags are ignored;
if “taxi” or “transportation” – or both – have already been added, the action
leaves them untouched. But if one or both tags were forgotten, this agent
automatically adds them.

Currency Conversion
When we add an expense item, we write down the $Amount we paid and the
$Currency we used. In the US, the value of $Currency will be “$”, in the
42
UK, $Currency will be “£”, in the EU, “€”. Our company maintains
accounts in dollars, and Ms. Nakamura will want to be reimbursed in dollars;
naturally, we want to be clear and consistent in converting currency
Inside the Infrastructure container, you will find a container named
“currency conversion” that automates conversion of other currency into
dollars. The first agent, “$”, simply copies $Amount to $Dollars since no
conversion is needed:
Name:&
&&$

Query:&inside(/Infrastructure/all&expenses)&$Currency="$"

&
Action:& $Dollars=$Amount&

The next agent, “€”, converts euros to dollars:


Name:&
&&€

Query:&inside(/Infrastructure/all&expenses)&$Currency="€"

&
Action:& $Dollars=$Amount*$ExchangeRate(/Config/euro)&

Whenever this agent finds an expense denominated in euros, it multiplies the


base amount by the value of the user attribute $ExchangeRate taken from
the note named “euro” in the container Config. When filing the expense
report, we simply fill in the current exchange rate in this note, and all euro-
denominated expenses will automatically be updated.
The agent “£” does precisely the same thing, using /Config/£:
43
Name:&
&&£

Query:&inside(/Infrastructure/all&expenses)&$Currency="£"

&
Action:& $Dollars=$Amount*$ExchangeRate(/Config/£)&

Similar agents convert Swiss Francs (CHF) and Israeli Shekels (ILS). We
never need to record more than one amount per transaction, and there is no
risk of an accidental mistake or inconsistency when applying conversion
rates.

Saving Steps: Copying Currency


Next, let’s revisit the raw expense reports.
Click the left-most tab “Expense Account”
and scroll to the top of the outline. Select
the note “Boston” and view its OnAdd
action in the Action Inspector.
Boston uses the prototype “City” and
inherited this action from its prototype. The
action contains four distinct steps: whenever
we add a note inside Boston,
1. The note’s $City is set to the name of its parent,
which is “Boston”.
44
2. The note’s $Prototype is set to "Expense."

3. If no $Currency has been specified, the note’s $Currency is set to the $Currency of its
parent. The currency of Boston is “$”, so expenses in Boston will use dollars unless you
specify otherwise.

4.If no $StartDate has been specified, the note’s $StartDate is set to the start date of the
previous sibling in that city.

Note that these are all initial assumptions, not hard and fast constraints. If
we want the note to be a summary, we can change the prototype from
“Expense” to “Summary”. If we want to specify a different date or use a
different currency, we are free to do so. By providing reasonable guesses,
Tinderbox saves time and avoid missing data.

Saving Steps: Initial Values


The City notes in our expense container serve two functions. First, they
organize expenses according to the major stops in our trip, breaking up the
long list of expense records into manageable segments. Second, each City
container has an OnAdd action, inherited from the prototype, which enters
some preliminary guesses about each newly-created note.
OnAdd:&$Prototype="Expense";&$City=$Name(parent);&$Currency&|=&
$Currency(parent);&$StartDate&|=&$StartDate(prevSibling)&
45
When we create a note inside a city, Tinderbox takes several actions:
• Tinderbox guesses that the note is likely to be an Expense, and sets the
prototype accordingly.
• Tinderbox guesses that the City in which the expense was incurred
corresponds to the City in which we were staying. This might be wrong –
we might have been visiting a suburb or we might have been in transit to a
new destination – but it’s a reasonable first assumption.
• The currency for the expense is set to the Currency used in that city.
Again, this might be incorrect, but it’s a good first guess. We use the
conditional assignment operator |= here so that the assignment is ignored
if $Currency already has a value – if, for example, we’re moving an
expense record that we’d accidentally filed in the wrong place.
• The $StartDate for this expense, if it hasn’t already been set, is the same as
the $StartDate for the expense immediately above it. This lets us rapidly
enter several expenses for the same date.
OnAdd actions are only performed when we create a note or add that note to
a new container; they’re suggestions, not constraints. If Tinderbox guesses
that we wanted to make an Expense but we really wanted to create a new
46
Summary, we simply change the prototype for the new note. Tinderbox
might guesses that we had lunch in London, since that’s where we are
staying; if we were actually in Oxford, we simply change the City.

47

7. Progress Bars
Inside the Expense Account container, we have three kinds of notes:
• Summaries provide narrative context for each day

• Cities mark arrivals in each new place

• Expenses record individual expenditures

It is clearly desirable to record each expense promptly, while the details are
fresh in our mind. Summaries are indispensable and mandatory, but these
always pose a problem. First, the traveller is frequently exhausted at the end
of the day, and the last thing he or she wants to do is to stay up writing a
narrative for the Accounting department. Second, the key elements from the
day’s activities might not always be immediately apparent, and a few day’s
perspective may help focus the summary on the most consequential matters.
Nevertheless, the summary is important and ought to be written while
matters remain fresh in our mind. One section of the Status dashboard keeps
track of summaries and draft summaries, reminding us of what has been
done and what remains to do.
48
Open the Status tab and scroll to the
upper right-hand section of the map
to find the Summaries dashboard.
At a glance, we see that we have
written six summaries, one of which
is very short. We have an additional
eighteen notes that use the prototype
“Draft Summary”. Fifteen have yet
to be written, and two more are very
brief.
If we go to the Expense Account tab,
we might change the prototype for
the April 24 summary back to Draft
Summary. Right-click the icon to
the left of the note title and select
Draft Summary from the menu of prototypes. Return to the Status tab; we
find that we have one fewer summary and one more draft. Go back to the
Expense Account tab and change the April 24 summary back to Summary;
the Status tab will return to its previous state.
49

Working With Progress Bars


Before examining the details of these status-monitoring tools, it may be
helpful to explore how progress bars work.
To begin, create a note named “Progress.” Use the Appearance inspector to
modify its appearance as follows:
Color:&&“6”&
Accent&Color:&“3”

Border&Color:&black

Border&Style:&plain

Border&Width:&narrow

Shadow:&off&(unchecked)&

Then, use the Text inspector to add a subtitle.


Title&alignment:&center

Subtitle:&42&
Subtitle&Color:&green&
Subtitle&Size:&(see&illustration)&

Finally, open the Plot pane of the Appearance inspector


and choose “bar” from the Pattern menu. Enter
$Subtitle in the plot’s Expression field, and ensure that
Minimum and Maximum are empty.
50

If no explicit minimum or maximum are chosen for a progress bar,


Tinderbox assumes that minimum is 0 and the
maximum is 100. As we see above, the progress bar is
roughly 42% full.
If we prefer a vertical gauge, we select vbar rather than
bar from the Pattern menu.
If you now change the subtitle from “42” to, say, “75”, the proportions of
the bar will be updated to reflect the new value.

Expected Progress
Next, select the note named “summaries” and open the Rule pane of the
Action Inspector.
Rule:&$Subtitle=find(Prototype="Summary").size&

The rule makes a list of all the summary notes in the document, recording the
size of that list in the note’s subtitle.
51
Next, switch to the note’s Plot
inspector. The plot pattern is “bar”
– a progress bar – and the
expression being plotted is simply
the $Subtitle just set in the note’s
rule.
The bar’s minimum value is 0. The
maximum is:
1+$Subtitle(/Status/days).toNumber&

We already know the length of the


trip; in the preceding chapter, we
recorded the number of days
between the first and final expense in
the note “days.” We might well want
a summary for both the first and
final days of the trip, so the number
of summaries we expect is one
greater than the number of days in
the trip. Finally, because $Subtitle is
52
a string, we explicitly convert $Subtitle to a number with toNumber to ensure
that Tinderbox understands that we want to “+” to add two numbers
together, rather than to append the two strings.

Spotting Trouble
We might create Summary (or Draft Summary) notes as placeholders,
intending to come back later and flesh them out. The note “empty” finds
summaries with no text:
Rule:&$Subtitle=find(Prototype=="Summary"&&&$WordCount==0).size&

Similarly, “empty drafts” finds draft summaries without text.


Rule:&$Subtitle=find(Prototype=="Draft&Summary"&&&$WordCount==0).size&

The notes “short” and “short drafts” identify summaries and drafts that are
very short – less than 100 words long.
Rule:&$Subtitle=find(Prototype="Summary"&&&$WordCount>0&&&$WordCount<100).size&

Setting A Target
It can be difficult to write summaries immediately, but too often we may
return from a long trip to find that we’ve postponed writing summaries for
53
days on end. This can leads to long evenings of tedium, forgotten details, and
unpleasant memos from the Accounting Department.
The number of draft summaries is a useful indicator that
paperwork is piling up. For this trip, we might attempt a
resolution to keep: we’ll try to keep the number of
unfinished drafts down to three or four.
The progress bar’s target is specified in the Plot Inspector, and may be a
constant number (here it’s “4”) or an expression. The marker is drawn using
the note’s $PlotColor, alternating with the contrasting color from the
progress bar.

Color Coding
Dashboards might want to call attention to problems. In the example above,
we have too many unfinished drafts: we resolved to aim for four drafts at a
time, and we currently have 18.
We can use a rule to change the appearance of notes that require attention.
For example, we could use this three-part rule (in which we’ve added some
extra space a line-breaks for clarity on the page):
54
$MyNumber=find(Prototype="Draft&Summary").size;

$Subtitle=$MyNumber;

if($MyNumber>4){$SubtitleColor="dark&bright&red"}&else&{$SubtitleColor=;}&

First, as before, we make a list of drafts, count them, and store the result in
$MyNumber. Next, we copy that result to the subtitle. And third, if the
result shows that we have more than four drafts, we set the subtitle color to
dark bright red; otherwise, the action
$SubtitleColor=;&

tells Tinderbox to use the inherited or default $SubtitleColor.


Many visual properties of dashboard notes can be effective indicators like
this. $Color and $Color2 change the colors used by
the progress bar. $BorderColor changes the border
color and $Border changes its thickness. $Badge adds
an named image or “badge” to the note’s upper right-
hand corner.
if($MyNumber>8){$Badge="alert"}&else&{$Badge=;}&

adds a warning symbol if far too many drafts have piled up.
55

8. Seeing The Data


Pie Charts
In Chapter Six, we used a group of
agents to manage exchange rates,
converting currency from Euros,
Pounds, and Krona to dollars. We
might find it useful to see an
overview of the fraction of our
expenses that was remitted in each
currency. A dashboard pie chart can
do this at a glance.
☞As a rule, prefer progress bars and histograms to pie charts. The pie chart is generally
overused and is frequently uninformative. In addition, readers are not very skilled at
judging the relative sizes of arcs and wedges, making pie charts hard to read unless the
reader already knows that the chart means to convey. Still, when you need to examine
the proportion of a few categories, pie charts can be a good solution.

To begin, we create an agent “By Currency” that collects those agents we


defined in Chapter 6:
56
Query:&inside(/Infrastructure/currency&conversion)&$AgentQuery!=""&

Note that agents always have an AgentQuery, while regular notes have no
use for one, so locating notes with a query is a good way to locate agents7.
Next, select the “By Currency agent, open
the Appearance Inspector, and select the
Plot pane. Several settings merit noting.
• The pattern is “pie”, requesting a pie chart.
• Each child of the agent represents one
segment of the pie. In this case, each
currency agent represents one segment
• Expression can be any attribute or
combination of attributes we might wish to
analyze. Here, for each agent, we locate
all the children of the original agent and
sum their $Dollars values, giving us the
total expenditure in each currency.
• The background of the pie chart is drawn
7 Smart Adornments also have queries, but because agents never examine adornments that need not concern us here,
57
in Color “2’, and is opaque.
The pie chart legend is drawn to the
right of the chart, if space allows.
The colors used in the pie chart are
chosen in turn from a list of colors in
the note’s $PlotColorList; for this
note, the $PlotColorList is:
green;lighter&green;darker&
green;light&green;black;white;blue&

If you change the first color from green to red, the segment for $ will change
color.

Bar Graphs and Plots


We might perhaps be interested in how our expenses were distributed
throughout the trip. Are the expenses clustered at the start of the trip or the
end? We some periods especially costly?
A quick and easy way to visualize expenses over time is simply to build a
chronologically-sorted list of all the expenses, and then plot each expense.
58
Agent:&expenses&by&day

Query:&inside(/Infrastructure/all&expenses)

Sort:&&StartDate&
&

Once again, we request a plot – this time a bar graph


– inside the agent/
• The Expression for the plot is very simple: we draw a
vertical bar proportional to the cost of each
reported expense.
• A few plane tickets are especially costly. We choose
a maximum value of $1000 for the graph’s vertical
axis so small expenses like taxi trips remain visible.
• Often, the plot background is translucent to allow us to see notes inside
the agent or container. For clarity, we choose an opaque white
background.
We see some big expenses early in
the trip – the plane flight to Paris,
the hotel in Zürich. Costs diminish
for a time, but seem to gradually
escalate toward the end of the trip.
59
It might also be helpful to see how the costs are distributed. Are there lots of
expenses for the same amount? Are there anomalous expense reports? The
agent named distribution of expenses helps us keep an eye on these questions.
Agent:&distribution&of&expenses&(log)

Query:&inside(/Infrastructure/all&expenses)

Sort:&&$Dollars&
&

Where in expenses by day we set


the plot’s expression to display
$Dollars, here we use a
logarithmic scale by displaying
log($Dollars). We see a fairly
even distribution of costs, with
perhaps a somewhat fewer small
expenses than we might otherwise expect. This might suggest that we’re
simply not reporting expenditures that are very small, or that we’re simply
not making small expenditures.
60
Expense Account
Boston Paris London: WatchfulCon
Friday, 24 flight to Saturday, 25 Sunday, 26 April Draft: Friday,pub
1 May
lunch Draft: Saturday, 2 May
April Paris April registration Draft: Sunday, 3 May
lunch
evening dress lunch dinner hotel
guidebook Oyster Card dinner
Louvre dinner drinks

power adapter
taxi
hotel Tel Aviv
maps Draft: Monday, 4 London->Tel
flight: Draft: Tuesday, 5 May
May dinner Aviv
Draft: hotel flight
Wednesday, 6
Dijon Zürich
May
Monday, 27 Tuesday,
April 28 train lunch
April Vienna
taxi to toy
dinner Draft: Thursday, 7 May pharmacy
Holmbrich Security:
breakfastretainer
(suppl)
coffee ontaxi
trainto hotel lunch
hotel Draft: Friday, 8
dinner hotel clinic May
taxi to Alliance
Against Marrakesh
Exploitation
Draft: Saturday, 9
May hotel lunch
near Como
Wednesday,lunch
29 April workout clothes
Ouarzazate Gothenburg
flowers hotel dinner dinner Draft: Monday, Draft:
11 MayWednesday, 13 May
breakfast

Draft: Thursday, Draft: Friday, 15


14 May May

Torino
car rental
Draft: Tuesday, 12 May Stavanger
Draft: Thursday, 30 April Bar Z
Draft: Saturday, 16 flight
traffic fine return rentalflight
car to London May
flowers
flight Boston
lunch Draft: Sunday, 17 May taxi

9. Treemaps
61
The Treemap view is designed to display the structure of your Tinderbox
document in detail by using screen space efficiently. On my Macintosh, an
outline can only display about 25 notes at a time, but the treemap can easily
display more than 100 notes while showing how they are related.
To begin, select the rightmost tab named “Expense Account” in the sample
document. This opens a treemap view of the Expense Account container, just
as the leftmost tab opens an outline view of that container.
Each note appears in the treemap as a rectangle. If a note has children, its
interior is divided among its children. Those children, in turn, divide their
interior space among their children. This continues until we’ve drawn all the
notes, or until the notes become too small to see.
The area of each note is proportional to the number of descendants that not
contains. Within the parent rectangle, notes are arranged roughly in order,
right-to-left and top-to-bottom, though Tinderbox can move notes around to
help make sure everything fits.
62
As in other views, click on any note to select that note. Double-click a
container to focus the view on that container; or use the breadcrumb bar to
expand the view to the parent note’s container.

Weighted Treemaps
Initially, treemaps apply equal weight to
every note. We can instead tie the area of
each note to that note’s properties. For
example, we might make the areas of each
note proportional to the expense it records.
In the treemap tab, note the small “Info” button. Click that button to display
the the treemap popover.
The treemap expression can be any
numerical expression. If a note’s
result is zero or negative, that note is
omitted from the treemap;
otherwise, the note’s area will be
roughly proportional to the result and the sum of the results of the note’s
descendants.
63
Expense Account
Expense Account Boston
flight to Paris
London: WatchfulCon
Oyster Card
registration dinner hotel

Boston London: WatchfulCon dinner

theater

flight to Paris Oyster Card


registration dinner hotel Tel Aviv
flight: London->Tel Aviv hotel flight

dinner

theater
Vienna
clinic Holmbrich Security: retainer hotel

Tel Aviv Paris

dinner
evening dress

flight: London->Tel Aviv hotel flight


hotel

Marrakesh
hotel

Dijon Zürich

dinner hotel
Ouarzazate Stavanger
dinner car rental flight flight

near Como

flowers hotel dinner

Torino
traffic fine return rental car

Vienna
clinic Holmbrich Security: retainer hotel

Paris

dinner
evening dress
hotel

Marrakesh
hotel

Dijon Zürich

dinner hotel
Ouarzazate Stavanger
dinner car rental flight flight

near Como

flowers hotel dinner

Torino
traffic fine return rental car

Here, the treemap expression is simply $Dollars: each Expense note is


drawn with an area proportional to that expense; bus fares are very small and
costly hotels are much larger. We also use $Dollars for the color expression:
the least costly expenses are white and the most expensive are green.
64
Note that the daily summaries no longer appear in the treemap; because they
do not record an expense, their $Dollars attribute is zero and they are
omitted. The very-expensive last-minute flight at the start of the trip
occupies a great deal of space; the pre-flight snack and guidebook, which
were accorded equal weight in our first treemap, are now tiny slivers to the
right of the plane ticket. Expense Account
Boston
flight to Paris
London: WatchfulCon
Oyster Card
registration dinner hotel
dinner

theater

Color Coding
Tel Aviv
flight: London->Tel Aviv hotel flight

The color expression can be used to Paris


Vienna
clinic Holmbrich Security: retainer hotel

highlight specific elements in the


dinner
evening dress
hotel

Marrakesh
hotel

treemap. For example, try this color


Dijon Zürich

dinner hotel
Ouarzazate Stavanger
dinner car rental flight flight

expression: near Como

flowers hotel dinner

Torino
traffic fine return rental car

&
&&&&&&&if($Tags.contains(meal)){1}else{0}&

Expenses for meals will use the End Color; other expenses will use the Start
Color.
We might want to identify transactions that use various currencies. We can
use the same approach to color transactions in currencies other than dollars:
&
&&&&&&&if($Currency!="$"){1}else{0}&
65
Here, if $Currency is not “$” the treemap uses EndColor – light green –
while if the $Currency is “$” the item uses StartColor – off-white.
Perhaps we want distinct colors for transactions in dollars, euros, and in
other currencies. We could use nested if() statements to accomplish this:
if($Currency=="$"){0}else{if($Currency=="€"){0.5}&else&{1}}&

Now, if the expense was in dollars, we use


StartColor, and if it was in euros, we use a mix
Expense Account
Boston London: WatchfulCon
flight to Paris Oyster Card
registration dinner hotel
dinner

theater

Tel Aviv

half-way between StartColor and EndColor.


flight: London->Tel Aviv hotel flight

Vienna

Nested if() statements can quickly become


clinic Holmbrich Security: retainer hotel

Paris

dinner
evening dress
hotel

Marrakesh

confusing. Tinderbox lookup tables can be a handy


hotel

Dijon Zürich

dinner hotel
Ouarzazate Stavanger
dinner car rental flight flight

alternative. We begin with a list of values of near Como

Torino
flowers hotel dinner

$Currency and the corresponding color value – for


traffic fine return rental car

example:
"$:0;&£:0.33;&€:0.66;&default:1"&

Each value of interest is paired with its associated value, separated by a


colon. The special key value default matches any unspecified value. The
ColorExpression is now:
"$:0;&£:0.33;&€:0.66;&default:1".at($Currency)&
66
To make the result clearer, we use a slightly darker green for EndColor.
Now, transactions denominated in dollars, euros, pounds, and in other
currencies can be identified at a
glance.
Expense Account
Boston Paris Dijon
flight to Paris evening dress
Zürich

Even though lookup tables are


dinner hotel

simpler to use than complex nested


if() statements, typing them more
near Como
dinner
flowers hotel
hotel
Torino

than once can be unwieldy. Instead, traffic finereturn rental car

we can store them in a configuration


London: WatchfulCon
Tel Aviv Ouarzazate Stavanger
flight: London->Tel hotel flight dinner flight
Aviv

note. Just as we refer to


registration

$ExchangeRate(/Config/£) to find dinner


car rental

the exchange rate for sterling, we


Vienna

clinic Holmbrich Security: retainer hotel


hotel flight

could save the lookup table in


$MyString(/Config/treemap). Now, Marrakesh
hotel

our color expression is simply:

$MyString(/Config/treemap).at($Currency)&

S-ar putea să vă placă și