Puzzling through a looping issue

Just searching for some creative ideas here.

I have a note called Essays, with 4 child notes, each child describing a scoring category for the essay, with a single user attribute, “score.” Typical structure would like like this:

Essay on birds

   Creativity

   Length

   Accuracy

   Examples

I want to loop through the child notes of the essay, calculating the average score values for Creativity and Length, and for Accuracy and Examples. Then store those average score values in attributes of the Essay parent note.

Ultimately I want to do this exercise for lots of different Essays, but all with the same child note titles.

Any pointers as I head to write action code?

Thanks in advance …

To clarify:

  • are the child notes always in the same order?
  • assuming ‘yes’ to the last, you want the parent to store two averages, each based on two child notes?
  • assuming ‘yes’ to the last, you want average #1 to use children #1 and #2, and average #2 to use children #3 and #4?
  • child notes store their score in a Number-type $Score (you can change code below if you use a different name but data type should be ‘Number’.

Sorry for apparent pedantry but code is more hard-edged than human description. :slight_smile:

So, let’s assume 2 Number-type user attributes $Avg1 and $Avg2. clearly you’ll have better names and can adjust the code accordingly.

We’ll assume all parent containers use a prototype "pEssay). Again you can rename adjust. The is prototype with use an edict (or rule):slight_smile:

var:list vList1;
var:list vList2;
vList1 = collect_if(children,($SiblingOrder==1|$SiblingOrder==2),$Score);
vList2= collect_if(children,($SiblingOrder==3|$SiblingOrder==4),$Score);
$Avg1 = vList1.avg();
$Avg2 = vList2.avg();

Once you understand what’s happening, a shorter form of the above is

$Avg1 = (collect_if(children,($SiblingOrder==1|$SiblingOrder==2),$Score)).avg();
$Avg2 = (collect_if(children,($SiblingOrder==3|$SiblingOrder==4),$Score)).avg();

As the code is in the prototype all Essay notes using the prototype run the same code. You might want to set the prototype’s Displayed Attributes to include $Avg1 and $AVg2 (or whatever name you use.

†. Edicts I find better a a bad rule runs all the time. Edict being on a slower cycle, gives to a chance to fix an error before hilarity ensues. But rule or edict is you child

1 Like

Thank you, Mark! All four of your clarifications were spot-on … turns out I needed some discipline.

Perfect solution; I tried many lengthy and verbose alternatives, but never considered using $SiblingOrder.

Great. :slight_smile:

Before someone asks, what is the desired children weren’t neatly grouped or their order might vary. If so, we could do something like add a String $ScoreGroup—even if we store a number ("1" vs letters "A" we want Tinderbox to know it’s not a number we want for paths).

Tip: If you use a prototype for the children, then adding/configuring these attributes gets easy.

So in $ScoreGroup we might store a different value for those notes that need it. So group 1 might store “A”, group 2 store “B”, etc.

Now the code becomes:

$Avg1 = (collect_if(children,($ScoreGroup=="A"),$Score)).avg();
$Avg2 = (collect_if(children,($ScoreGroup=="B"),$Score)).avg();

Obviously, if you also have more groups, this scales too:

$Avg1 = (collect_if(children,($ScoreGroup=="A"),$Score)).avg();
$Avg2 = (collect_if(children,($ScoreGroup=="B"),$Score)).avg();
$Avg3 = (collect_if(children,($ScoreGroup=="C"),$Score)).avg();

// ...etc.

Indeed, if you have lots of averages, you might use a dictionary in the parent container so one attribute holds multiple values that have discrete addressing. So, with a Dictionary-type $Averages:

$Averages["gpA"] = (collect_if(children,($ScoreGroup=="A"),$Score)).avg();
$Averages["gpB"] = (collect_if(children,($ScoreGroup=="B"),$Score)).avg();

All very flexible and note how little work it takes to extend, or make more flexible, the original design.

1 Like

Attached is a demo version of my full TBX file, implementing the scoring code that you provided … many thanks!

Each essay has a prototype that includes the 9 children scoring elements, so that in addition to scoring numerically, I can add extracts, comments, assessments, etc.

I’ve only included 2 essays, but this will scale to many more.

Also, future versions could include a poster note that pulls the scores and displays a radial chart for a given essay; I’ve prompted Claude AI to start that process, and included its response in a separate note.

All progress, and many thanks for the key ideas!

demo Art of the Essay.tbx (626.8 KB)

2 Likes

Thanks for sharing. I think actually seeing the ideas/code working in a file can be a help for others trying to do similar things.