Tinderbox User-to-User Forum (for formal tech support please email: info@eastgate.com)
http://www.eastgate.com/Tinderbox/forum//YaBB.cgi
Tinderbox Users >> Agent, Actions, Rules & Automation >> Collecting linked notes from different containers
http://www.eastgate.com/Tinderbox/forum//YaBB.cgi?num=1276135543

Message started by Rigas Arvanitis on Jun 9th, 2010, 10:05pm

Title: Collecting linked notes from different containers
Post by Rigas Arvanitis on Jun 9th, 2010, 10:05pm

Hi to all

I need to select notes representing different objets and linked by a common attribute (as in a relational database).

On one hand I have "articles" with an attribute "Number" (of the article)
On the other hand I have "referees" that read the articles and they have an attribute "Number" which contains the number of the article they are refreeing.

I want to collect a pack of articles (with some agent) -for instance articles sent since two months, or corresponding to a same issue of the journal- and  list all the referees involved with these articles.

Simple ! Well, I am unable to find a solution to this (rather) simple query...

Rigas

Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 10th, 2010, 3:54am

This probably requires 2 agents.  The first matches all articles meeting a criteria ($PubDate> ????, $IssueNumber==? or $IssueNumber>?) - hard to be exact as you don't note how Issues/Volumes are recorded. Anyway, that agent's rule makes a set  - $ArticleSet using collect() -  of all $Article numbers used by the agent's matches.

A second agent then finds all notes of type Referee whose $ArticleNumber matches any of those those in the above agent's $ArticleSet. Assuming the $Names of the referee notes are the names of the referees, then looking at the second agent will show you the referees. If you need to export them as a list, use collect() again to make a set of all the names and export that as a list.

If the above answer is loose it's only because there's insufficient detail in the original question to cite actual attributes, etc., and thus give exact code.  I also wonder how you deal with the scenario of someone who referees more than one article. If $ArticleNumber is a set, then the above method won't work (though some other variant likely will).

If you want more detailed help, post a small example. There's no better way of testing a solution than on actual data. The example should include data you do and don't expect in the final match. The latter is important so we ensure no false positives.

Title: Re: Collecting linked notes from different containers
Post by Rigas Arvanitis on Jun 10th, 2010, 3:05pm

Mark

thanks a lot  for the suggestion. Two agents: That I suscpected. The problem now is my coding skills in TB are nil.

I just created an example file as you suggest. Its really based on the same architecture of my file but its simplified (an d names corespond to nothing real ). The real file has more than 100 articles and about two hundred referees and more than 500 links ! Where can I send the example so you get a grasp of it?

Image below shows you :
- AUthors (upper left)
- Referees (called "Lecteurs" in our French jargon, lower left)
- Articles on the upper right which as you see in the example are gathered in containers correponding to the value of $Dossier (an attribute of the proto "article"). Then I have a series of agents to monitor the activity (called 'alertes').


Click for full size - Uploaded with plasq's Skitch


- For each article I have a lot of attributes: NumArticle, name of the author (Auteur), the name of the referees, etc... One important attrbute is the $Dossier which gather articles to be published in teh same feature in the journal. "Varia" is the name for articles outside a Dossier.


Click for full size - Uploaded with plasq's Skitch


- For referees I have names in the title of the note and some othe rattributes, but the only common info I have with tha articles is the number of the article.


Click for full size - Uploaded with plasq's Skitch


The whole things works reasonably well, but I would like to have an output that lists a series of articles (whatever criteria) then the list of referees (or/and authors) which is linked either by links (although links are erratic, because you have to build them by hand each time and this i ssomething you never really control) or just because I have them listed somewhere else (in a cotainer called "Lecteurs") and I can find them by the $NumArticle.

I also created a set attribute $ArticleSet which will contain the numbers of the selected articles.

- Agent one is whatever criteria for the query that selects the articles. Where do I put the collect() in the agent? In the rule box? What is the syntaxis (I dont understand the manual...)  ::)

- Agent two will collect the referees based on the $ArticleSet content ! Again what synatxis and where.

As to your question what do I do with a sole person being a referee for two or more articles, that never happens at the same time !!  ;)

One we fine tune all this, I very gladly can post the whole exercise in the examples of uses if TBX !

Rigas

Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 10th, 2010, 6:33pm

Thanks for taking the trouble with all the grabs.

So, Agent 1's query finds the article (what query are you using?). In the agent's $Rule put this:

  $ArticleSet=collect(child,$Lecteur1);$ArticleSet=$ArticleSet+collect(child,$Lecteur2)

Assuming $ArticleSet is a Set-type attribute, the $ArticleSet for Agent 1 will hold the names of every $Lecteur1 in the matched items. [more later...]

Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 10th, 2010, 6:46pm

Agent2 as earlier proposed may not be possible due to limitations in the way a set may be queried. The only way to test a set is to use the AttributeName(pattern) operator. Agent 2 needs to be able to do something like:

  ($Lectuer1=ArticleSet(agent)) | ($Lecteur2=$ArticleSet(agent)) (NOT VALID SYNTAX!)

I'll have to think on this.

Title: Re: Collecting linked notes from different containers
Post by Rigas Arvanitis on Jun 10th, 2010, 7:54pm

Agent1 is something like that :

Query to look for articles of a specific Dossier where I miss one refereeing:

$Dossier="Ressources biologiques" & $Prototype="article" & $ArticleFini=false & EnAttente=false& $EvaluationEnCours=true& $EnRevisionAuteur=false& ($AvisLecteur1="manque"|$AvisLecteur2="manque"|$AvisInterne="manque")

which translates:

- Dossier is on "Ressources biologiques",
- I focus on notes that are articles,
- that are not published or rejected already ($ArticleFini means finished article and needs to be false),
-  where I am not waiting some input ($EnAttente=false),
- which is still in the process of evaluation ($EvaluationEnCours=true)
- has not been sent back to the author ($EnRevisionAuteur=false)
- and I miss at least one refereeing note ($AvisLecteur1="manque"|$AvisLecteur2="manque"|$AvisInterne="manque")


Now agent2:

Well I would rather make the set on $NumArticle. And then ask somehow to list all notes that are $Prototype "lecteur" (referee) and have an attribute $NumArticle to be found inside the set $ArticleSet.

How does that sound?

$ArticleSet is a set attribute

$ArticleSet=collect(child,$NumArticle)

Then I need another agent, agent3 that would seek inside ArticleSet to list the notes corresponding to the names of the referees that have refereed these paper in ArticleSet...

What would be the syntaxis?

WHERE should the agents be located? Because child refers to a specific location.... Right?

Another possiblity is to create a sort of note that contains only the name of referee + name of article....


Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 11th, 2010, 7:11am

Agent 1 simply shows the power of Tinderbox.  Use as many parameters as you need

As you asked about syntx, to follow best practice, I'd add (red) a '$' before 'EnAttente'. White space before/after &, |, (, or ) doesn't matter and is down to clarity/personal tase:

$Dossier="Ressources biologiques" & $Prototype="article" & $ArticleFini=false & $EnAttente=false & $EvaluationEnCours=true & $EnRevisionAuteur=false & ($AvisLecteur1="manque" | $AvisLecteur2="manque"| $AvisInterne="manque")

Can Agent 1 collect $NumArticle? Yes - I was just guessing at titles. However you will need a new Set-type user attribute to hold the result of the collect(). The collect(), collect_if(), links() [url=]create data in set form[/url]so when using these the left side must always be a set attribute. This is fine:

Rule:   $ArticleSet=collect(child,$NumArticle)

The above is either the $Rule in Agent 1, populating the agent's $ArticleSet, or, ... it with the syntax below and placed in the agent's $AgentAction it could populate $ArticleSet for note 'Some note' like so:

AgentAction:   $ArticleSet(SomeNote)=collect(child,$NumArticle)

Where do agents need to need placed? It doesn't matter. An agent's children are the result of it's query and will be the same wherever the agent is placed.  Answering another implied qurestion, collect() can target a group (collect syntax) based on a different note. So note X can collect from note Y's context:

Rule in Note X:   $ArticleSet=collect(child(Y),$NumArticle)

All of which is fine but there's no way to

Quote:
to list the notes corresponding to the names of the referees that have refereed these paper in ArticleSet


Or rather, we've gone about this the wrong way! As is so often the case with TB, when thinking how to explain why the route I'd tried doesn't work, the answer becomes clear.  OK, Agent 1 lists all the articles that are relevant. Each article note has the name of its readers ($Lecteur1 & $Lecteur2). So, agent 1 actually has the info we need. Make a new Set-type attribute 'LesLecteurs' (if my schoolboy French is correct!). Re configure Agent 1 like so:

Agent's Query:   $Dossier="Ressources biologiques" & $Prototype="article" & $ArticleFini=false & $EnAttente=false & $EvaluationEnCours=true & $EnRevisionAuteur=false & ($AvisLecteur1="manque" | $AvisLecteur2="manque"| $AvisInterne="manque")

Agent's Action:     $LesLecteurs(agent)=$LesLecteurs(agent)+$Lecteur1;$LesLecteurs(agent)=$LesLecteurs(agent)+$Lecteur2;

The set $LesLecteurs of Agent 1 now holds a list of all the readers (lecteurs) who have read the the articles found by the query. As well as showing a result this thread shows how there's more than one way to a solution and if something like a desired syntax (set querying) isn't available there's usually another way around. Also, it doesn't matter where Agent 1 lives and the query/action code doesn't mind what you actually call 'Agent 1' - I suspect something in your native tongue might make more sense, e.g. 'Agent: liste de lecteurs'.

Title: Re: Collecting linked notes from different containers
Post by Rigas Arvanitis on Jun 15th, 2010, 5:11am

wow !

Your French is perfect.

This is a great lesson here. Thanks a lot Mark.

Rigas

Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 15th, 2010, 6:09am

To make it easy to view the list of readers and if you don't already use the text of agent 1 for anything, you could add this rule:

Rule:  $Text=format($ArticleSet,"Les lectuers pour ces articles:\n","","\n","");

This gives you the heading "Les lectuers pour ces articles:" ending in a line break and then each reader's name on a new line.  Being a rule, as $ArticleSet changes, the $Text is updated.  It does mean the you can' easily mix this output with other general text in the same note/agent.

For more, see format().

Title: Re: Collecting linked notes from different containers
Post by Rigas Arvanitis on Jun 15th, 2010, 7:13am

Formatting the $Text works fine ! (everything is an attribute, would say Mark B).

For some reason my attribute (of set type) $Lecteurs doesnt seem to collect the info...

My agent called "manque avis" (some review is missing) collects the info (the referees missing)


Click for full size - Uploaded with plasq's Skitch

It seeks in the specific dossier "Ressources biologiques" all articles that have a missing referee review (they are Lecteur1 Lecteur2 LecteurInterne)



Click for full size - Uploaded with plasq's Skitch

Query : $Dossier="Ressources biologiques"&
$Prototype="article"&$ArticleFini=false&$EnAttente=false&$EvaluationEnCours=true&$EnRevisionAuteur=false&($AvisLecteur1="manque"|$AvisLecteur2="manque"|$AvisInterne="manque")


(same as above - works fine, collects effectively the five articles in this dossier where I still wait for reviews from referees)

There are two actions: collecting the names of the referees in the set $LesLecteurs and collecting the # of the articles where we miss a review, in the attribute $ArticleSet.

Action : $LesLecteurs(manque avis)=$LesLecteurs(manque avis)+$Lecteur1;$LesLecteurs(manque avis)=$LesLecteurs(manque avis)+$Lecteur2;$LesLecteurs(manque avis)=$LesLecteurs(manque avis)+$LecteurInterne;$ArticleSet=collect(child,$NumArticle)

And finally the text of the agent shows the results of both sets. In this case I have 5 articles where I still wait to receive reviews from referees.

Rule:  $Text=format($LesLecteurs,"Les lecteurs pour ces articles:\n","","\n",""); $Text=$Text+format($ArticleSet,"Les  articles:\n","","\n","");

I must miss something because the attribute Les Lecteurs never gets filled with anything....  as you can see below : :-[


Click for full size - Uploaded with plasq's Skitch

I dont understand. Should the action refer to "agent" instead of the name of teh agent? I tried, gives the same result. I update agents, same thing.


Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 15th, 2010, 8:31am

Surely, if you're collecting articles missing reviewers, there will be...no reviewers. However, I believe you're looking for reviews where there is only one lecteur when there should be two?

No obvious reason why the code's not working, espeaically as you can correctly get a list of articles via the same code method.  The first think I'd check is to expand the agent and view the aliases inside. Open each of these in turn and check if there is a value for $Lecteur1 or $Lecteur2. Any values for these attributes, should be the the list in the agent's $Text.

For an agent called "manque avis", in the $AgentAction, these codes are equivalent:

$LesLecteurs(manque avis) = ...
$LesLecteurs(agent) = ...

as both refer to the same agent. If you copied the code into an agent called "manque lecteur" the first code would fail as it refers to a particular agent whereas the second would still work as it referes generically to the current agent in use by the code.

Title: Re: Collecting linked notes from different containers
Post by Rigas Arvanitis on Jun 15th, 2010, 8:48am

Sorry i didnt make myself clear

Lecteur1, Lecteur2 are not missing values: they are names of the referees (I, as chef editor, still dont have the reviews and thats what I want the agent to tell me : which articles and which  reviewers/referees havent sent me their reviews).

So the attributes are there, and they have a value inside, a string a name of a person, in that case a referee !

Annoying, isnt it?



Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 15th, 2010, 9:50am

I think your ArticleSet data is a 'false positive' The collect should go in the agent's rule.  Delete this from the end of the agent action:

$ArticleSet=collect(child,$NumArticle)

Add the code to the front of the agent's Rule, because the child is meaningless in the context of the action.  In the rule it means child of this rule. The Rule now looks like:

$ArticleSet=collect(child,$NumArticle);$Text=format($LesLecteurs,"Les lecteurs pour ces articles:\n","","\n",""); $Text=$Text+format($ArticleSet,"Les  articles:\n","","\n","");

...which simplifies to...

$Text=format($LesLecteurs,"Les lecteurs pour ces articles:\n","","\n",""); $Text=$Text+format(collect(child,$NumArticle),"Les  articles:\n","","\n","");

Still looking at the other problem of the $LesLecteurs data...

Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 15th, 2010, 10:29am

Aha, must remember to keep old text files for a few days.  I had to rebuild my test file and I'm not sure why it worked before but I now find I need a different syntax as certain intuitive set syntax seems not to work (I'm sure it did but maybe I'm just confused!). It seems you can't do this:

$MySet(other note)=$MySet(other note)+"string value"

Basically, you can only add or subtract values within the current note, although you can set the current note's set to the value of the same attribute form another note:

$MySet=$MySet(other note)

So the +, - and ~ operators to add/subtract/toggle values in sets with existing values have to be done in the note. Furthermore, we can't use an attribute value for such an action - we must pass the evaluated version of the value:

$MySet=$MySet + eval($SomeAttribute)

Phew - lots of problems but once you know the syntax, the problem becomes easier. Back to your 'manque avis agent. The action is now this:

$LesLecteurs=$LesLecteurs+eval($Lecteur1);$LesLecteurs=$LesLecteurs+eval($Lecteur2);$LesLecteurs=$LesLecteurs+eval($LecteurInterne);

Notice how each article note is making its own article set. The agent then reads them by this revised rule:

$LesLecteurs=collect(child,$LesLecteurs);$ArticleSet=collect(child,$Article);$Text=format($LesLecteurs,"Les lecteurs pour ces articles:\n","","\n",""); $Text=$Text+format($ArticleSet,"Les articles:\n","","\n","");

If you like you can shorten the rule to the following - both work:

$Text=format(collect(child,$LesLecteurs),"Les lecteurs pour ces articles:\n","","\n",""); $Text=$Text+format(collect(child,$Article),"Les articles:\n","","\n","");

The latter is shorter but perhaps less clear when you're still learning and de-bugging the action code.

Just so I don't get confused again, a demo of the above is here.

Before someone asks these limitations in set syntax aren't in the Help file, release notes or aTbRef. Mark B's at a convention right now but when he's back I'll check the Set syntax with him and update aTbRef.


Title: Re: Collecting linked notes from different containers
Post by Rigas Arvanitis on Jun 15th, 2010, 11:48am

Ah! So syntaxis was the problem.

IT WORKS ! Yipee !!

I get an attribute $LesLecteurs Okay now, which contains the list of values of the attributes $Lecteur1, $Lecteur2, $LecteurInterne.

BUT, the collect() function eliminates all characters such as "/" or commas. If there is a comma in the value of the attribute such as for example "Arvanitis, Rigas" it retains the first word (Arvanitis) and discards the comma and what trails after the comma (the ", Rigas").

The other attribute, $ArticleSet contains the value of $NumArticle (mind you in your response up here you didnt write $NumArticle but just $Article, which produces the set to contain only one value "$Article" --...)

Very useful Mark, you did it again. Congrats !

(BTW the posted example is unreadable...)


Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Jun 15th, 2010, 12:38pm

The example file's fine, you probably just downloaded it incorrectly. Right-click the link (in Safari, anyway) and select "Save linked file to "Downloads"". Before you go do download again, I've also fixed a few more things - read on...

When TB is parsing strings '/' might indicate a folder delimiter in a path and ',' a parameter delimiter; under the hood the computer doesn't have the human's sense of context so it's parsing has to make some assumptions. I'd agree neither of these issues is desirable. I suspect they're more unintended consequences. As luck would have it, there is a simple workaround.  If you use a name with a comma or slash in it, put quotes in the original $Lecteur attribute - my demo now has examples but:

Before $Lecteur1 value: Mirauld, Colette  --> Mirauld
Now $Lecteur1 value: "Mirauld, Colette"  --> Mirauld, Collete
Before $Lecteur1 value: Guy/Betrand  --> GuyBertrand
Now $Lecteur1 value: "Guy/Bertrand"  --> Guy/Bertrand

You'll see that for name with a space in (see the updated demo) TB gets the string->set value right. Still, I suspect quoting a few names in the source attribute isn't too big a price to getting it all working today.

Sorry about the $Article vs $NumArticle name - this is why it's easier using someone else's test file - I don't have to figure out the data types etc - not that you haven't been extremely helpful with screen grabs, etc.

I think that fixed the latest round of errors! Updated file replaces the old one. Right click this link and save as... manque-avis.tbx

Title: Re: Collecting linked notes from different containers
Post by Mark Anderson on Mar 15th, 2011, 11:55am

Update to comments above...

The syntax does now work (testing in v5.8.0):

$MySet(other note)=$MySet(other note)+"string value"

I'm not sure in which version that got fixed - I can't find a Release Note specifically mentioning it.

From v5.8.0, the old stamp syntax of:

  $MySet = $MySet +a_string;          (gone from v5.8.0+)

...is no longer allowed - whether the argument is quoted or not. As a by-product of this the set ~ (toggle valaue) feature is also gone from v5.8.0+.

Tinderbox User-to-User Forum (for formal tech support please email: info@eastgate.com) » Powered by YaBB 2.2.1!
YaBB © 2000-2008. All Rights Reserved.