Tinderbox Forum

Getting right syntax in an edict - help please

Hi folks,
It would be appreciated if someone might be able to help me get the right syntax for an edict such as this one to be used for a Webinar event-style prototype please:
if($PanelistBioObtained==“true” & $PanelistHeadshotObtained==“true” & ($PanelistPrezoObtained==“true” {$Badge=“ok”;$EndDate=“today”;$Container="/archives"}} else{$Badge=“calendar”;$EndDate=“never”;
The goal here is to check if certain tasks have been completed (ie ticked to make them true), and, if each of the 3 attributes relating to the event’s 3 tasks are true, then change the badge to a tick, make the $EndDate be today and move the note into a category intended to contain completed event notes. But whilst 1 or more of the 3 tasks remains undone (ie unticked and therefore false) keep calendar as the badge and the end date never. For some reason, I can’t get the above code to do the job.
Separately, I’d also like to make one of the trigger conditions whether a transcript’s URL location has been added to a boolean attribute such as $TranscriptComplete. Is it true to say that for a string attribute (rather than a boolean one), if there is no entry for the attribute (ie in this case no local link has been entered) then it is deemed false? And if this assumption is correct, does the same assumption apply to the built-in NLtags-style of attribute? Thanks for any help.

Not at my computer at the moment, so just a quick idea.
Might it be that you need to put each of the expressions into parentheses?
Also, check the number of open and closed parentheses.

Let’s start by sorting out the code. We have:

if($PanelistBioObtained=="true" & $PanelistHeadshotObtained=="true" & ($PanelistPrezoObtained=="true" {
  $Badge="ok";$EndDate="today";$Container="/archives"}
}else{
   $Badge="calendar";$EndDate="never";

The syntax of a conditional is if(condition){true result code}else{false result code}. Your current code has mismatched parentheses (the condition is not closed) and brackets. Simplifying by using symboloc entries your code looks like:

if(A & B & 
   (true result code;}
}else{
   false result code;

Correcting obvious syntax errors, I think you mean to write:

if($PanelistBioObtained=="true" & $PanelistHeadshotObtained=="true" & $PanelistPrezoObtained=="true"){
  $Badge="ok";$EndDate="today";$Container="/archives"}
}else{
   $Badge="calendar";$EndDate="never";
}

Correction. Boolean values are never quoted:

if($PanelistBioObtained==true & $PanelistHeadshotObtained==true & $PanelistPrezoObtained==true){
  $Badge="ok";$EndDate="today";$Container="/archives"}
}else{
   $Badge="calendar";$EndDate="never";
}

Apart from that the query terms and actions both look OK. Ttry this corrected code and I believe it should function as desired.

So you also want ot test if $URL has been set for a note. A URL-type, like a String has a default value of no value, i.e. an empty string. This can be tested like so:

$URL=="";

or

$URL

The latter essentially asks, “does $URL have (non-default) value set?”

Any attribute, user or system can be tested in a query.

Not quite as a Date, for instance, has a default value of “never”. So the test for an unset date could be either of:

$MyDate=="never"
!$MyDate

The latter is essentially reversing the other short form (“Do I not have a value set?”). You could use MyDate==false but I’d recommend the above forms instead.

As to default values, see $AttributeName (short form test for value) and (!$AttributeName) (short form test for no value).

Quick suggestion before heading out to some 13thC New Mexico ruins.

When you are tempted to write an edict of the form:

if (some condition) { some action }

you should instead begin with an agent:

query: some condition
action: some action

Why? First, you can actually see, right away, which notes the action applies to. That’s a big help for debugging. If problems arise, it’s easier to see whether they lie in acting on the wrong notes, or in doing the wrong thing.

If you need an else clause, that’s another agent:

query: !(some condition)
action: some other action

Now, if you have thousands of notes, sure: edicts help keep you machine lively and don’t waste your battery. But once the agent is right, it’s easy to replace it with an edict.

Thanks gentlemen. So to combine all this much appreciated advice, I am now trying to divide up the correct code from @mwra with the structure suggested by @eastgate - but not quite getting it right still. If the approach is to write a fresh agent rather than an edict embedded in the prototype, which part of the code do I put in the agent’s query field and which part in the agent’s action field please? Attempts to put the “if” part in the agent’s “query” field, followed by pasting the rest of the code into the “action” field don’t have the desired effect. Or is it the case that when using the agent approach, the query should be stripped down and merely list the attributes that are to be true? at one point I found that my attempt became recursive with an alias of the note being added to the archive over and again (rather than moved into the archive just once) which was clearly a mistake on my part too…
In the last experiment, the “if” code was broken into two agents. In Agent 1, the query has $Prototype==“pEvent” & $BioObtained==“true” & $HeadshotObtained==“true” & $PrezoObtained==“true” and the Action has $Badge=“ok”;$EndDate=“today”;$Container="/Content/Archive"
Then in Agent 2, the query has $Prototype==“pEvent” & $BioObtained==“false” & $HeadshotObtained==“false” & $PrezoObtained==“false” and the Action has $Badge=“calendar”;$EndDate=“never”. But this form of instructions is what is creating the continuous addition of an alias of the note in the archive…

Initial point, boolean attribute true and false vaues are not quote enclosed in queries or in actions. I missed that in my earlier reply, which I correct after posting this.

I think two issues are getting confused:

  • how a query is defined
    *the context of its use

The original code above failed because the code was incorrect and wouldn’t get parsed correctly. User error, albeit unintentional.

Now to agent vs rule or edict. The difference? The scope of application. The code written above can be used in a rule, edict, stamp or agent action. They run as follows:

  • rule: run on the current note every rule cycle
  • edict: run on the current not less often (see edicts)
  • stamp: run on all selected note(s) but only once per application of the stamp
  • agent action: run every agent cycle on each child alias in the agent, i.e. on each note matching the agent’s query.

As your code is has different code for the true/false conditions, if using an agent, the agent query must find all notes that need to be tested, leaving the code branching as the current if/else is the agent action.

So In Agent 1, the query has 4 querry terms:

$Prototype=="pEvent" & $BioObtained==true & $HeadshotObtained==true & $PrezoObtained==true

So notes with the ‘pEvent’ prototype and with those 3 other conditions true will match the query and an alias for such notes is created in the agent. This action is then on on those aliases:

$Badge="ok";$EndDate="today";$Container="/Content/Archive";

Of course, every time the agent updates, the same action runs and the aliases is re-copied to the archive container. So the container /Content/Archive is now adding a new alias for each matching note, each cycle. What I thing you intended was that the original note of the alias is moved to the archive—and that needs doing only once.

So, add a new boolean attribute $IsArchived. Now the query is:

$Prototype=="pEvent" & $IsArchived==false & $BioObtained==true & $HeadshotObtained==true & $PrezoObtained==true

The new attribute is inserted second as we need to test only events and then only those ones which aren’t archived. The action becomes:

$Badge="ok";$EndDate="today";$Container(original)="/Content/Archive";$IsArchived==true;

Two changes. Frost we move the original note, not its alias. Second, we set the $IsArchived boolean meaning archived events no longer match the agent’s query.

Agent 2 looks OK, but archived notes can’t logically match so we’ll filter those in the query:

$Prototype=="pEvent" & $IsArchived==false & $BioObtained==false & $HeadshotObtained==false & $PrezoObtained==false

Action:

$Badge="calendar";$EndDate="never";

Does that help?

1 Like

Brilliant Mark. Sincere thanks. Working perfectly now. And both concepts and execution steps now very clear.

3 Likes

Excellent advice Mark and much appreciated. Hope the ruins met your expectations - particular thanks for responding on your vacation!