Complex Conditional Rule help


(Derek Van Ittersum) #1

I’ve tested a couple of rules and they work well. Now I’m trying to get them to work within conditionals, so I can apply the same Rule to all notes in the set.

Basically, I’ve two types of notes:

A) W1T, W2T, … W10T, W11T etc.
B) W1R, W2R … W10R, W11R etc.

(Week 1 Tuesday, Week 1 Thursday, etc.)

I want to add a start date to Week 1 Tuesday and Week 1 Thursday, then have all the other start dates for the notes set automatically. I’ve got the rules down for doing that, but am now trying to set conditionals to match any possible note.

This rule isn’t currently working (but all the rules in the if/then statements are working)

if($Name(compositeFor(this):role(ClassDate)).size=3){
	if($Name(compositeFor(this):role(ClassDate)).contains("T")){
			$ClassDateNumber=eval($Name(compositeFor(this):role(ClassDate)).substr(1,1))-1;$StartDate=date($StartDate(compositeWithName(W1T):role(ClassDate))+($ClassDateNumber + " week"))
				} else {
			$ClassDateNumber=eval($Name(compositeFor(this):role(ClassDate)).substr(1,1))-1;$StartDate=date($StartDate(compositeWithName(W1R):role(ClassDate))+($ClassDateNumber + " week"))				}
else {
	if($Name(compositeFor(this):role(ClassDate)).contains("T")){
			$ClassDateNumber=eval($Name(compositeFor(this):role(ClassDate)).substr(1,2))-1;$StartDate=date($StartDate(compositeWithName(W1T):role(ClassDate))+($ClassDateNumber + " week"))
				} else {
			$ClassDateNumber=eval($Name(compositeFor(this):role(ClassDate)).substr(1,2))-1;$StartDate=date($StartDate(compositeWithName(W1R):role(ClassDate)) +($ClassDateNumber + " week"))
				}
}

(Derek Van Ittersum) #2

Apparently I was just missing some braces. This appears to work:

if($Name(compositeFor(this):role(ClassDate)).size=3)
{if($Name(compositeFor(this):role(ClassDate)).contains("T")){
			$ClassDateNumber=eval($Name(compositeFor(this):role(ClassDate)).substr(1,1))-1;$StartDate=date($StartDate(compositeWithName(W1T):role(ClassDate))+($ClassDateNumber + " week"))
				} else {
			$ClassDateNumber=eval($Name(compositeFor(this):role(ClassDate)).substr(1,1))-1;$StartDate=date($StartDate(compositeWithName(W1R):role(ClassDate))+($ClassDateNumber + " week"))}

} else {

	if($Name(compositeFor(this):role(ClassDate)).contains("T")){
			$ClassDateNumber=eval($Name(compositeFor(this):role(ClassDate)).substr(1,2))-1;$StartDate=date($StartDate(compositeWithName(W1T):role(ClassDate))+($ClassDateNumber + " week"))
				} else {
			$ClassDateNumber=eval($Name(compositeFor(this):role(ClassDate)).substr(1,2))-1;$StartDate=date($StartDate(compositeWithName(W1R):role(ClassDate)) +($ClassDateNumber + " week"))}}
}

(Mark Anderson) #3

One error is using ‘=’ instead of ‘==’ for an equality test in a query. The composite code is new and may not have legacy support (thus my seeming pedantry about using the correct operators :wink:).

However, it could be an issue where eval() is needed to properly fix the value of compositeFor(this):role(ClassDate). I notice you’re already using eval() within the nested actions. I’d try:

if(eval($Name(compositeFor(this):role(ClassDate)).size)==3){
   ^^^^                                       ^^^

…and similar for the nested if() queries.

As you use $Name(compositeFor(this):role(ClassDate) a lot you might consider getting the $Path for this at line one an using a ‘var’ for the rest of the code. More on var. Edit: the reason this is wrong is explained in my next post below

Given the hoops you’re jumping through, I sense a bit of incremental formalisation might help. Don’t overlook the fact that adding an attribute to hold a value you’re currently trying to parse from a string might save you a lot of on the fly parsing vs. just reading an attribute value.


(Derek Van Ittersum) #4

aha. even better:

$MyString=$Name(compositeFor(this):role(ClassDate));
if($MyString.size==3)
    {if($MyString.contains("T")){
        $ClassDateNumber=eval($MyString.substr(1,1))-1;$StartDate=date($StartDate(/Schedule/W1T)+($ClassDateNumber + " week"))
	    } else {
    $ClassDateNumber=eval($MyString.substr(1,1))-1;$StartDate=date($StartDate(/Schedule/W1R)+($ClassDateNumber + " week"))}
        } else {
    if($MyString.contains("T")){
			$ClassDateNumber=eval($MyString.substr(1,2))-1;$StartDate=date($StartDate(/Schedule/W1T)+($ClassDateNumber + " week"))
				} else {
			$ClassDateNumber=eval($MyString.substr(1,2))-1;$StartDate=date($StartDate(/Schedule/W1R)+($ClassDateNumber + " week"))}}
}

Whew, it’s a bit of a mental workout making all those braces match up.


(Mark Anderson) #5

Yes, though I think you’ve one too many closing ‘}’ but as it’s at the end it has no effect on execution. So we get:

$MyString=$Name(compositeFor(this):role(ClassDate));
if($MyString.size==3){
   if($MyString.contains("T")){
      $ClassDateNumber=eval($MyString.substr(1,1))-1;$StartDate=date($StartDate(/Schedule/W1T)+($ClassDateNumber + " week"))
   } else {
      $ClassDateNumber=eval($MyString.substr(1,1))-1;$StartDate=date($StartDate(/Schedule/W1R)+($ClassDateNumber + " week"))
   }
} else {
   if($MyString.contains("T")){
      $ClassDateNumber=eval($MyString.substr(1,2))-1;$StartDate=date($StartDate(/Schedule/W1T)+($ClassDateNumber + " week"))
   } else {
      $ClassDateNumber=eval($MyString.substr(1,2))-1;$StartDate=date($StartDate(/Schedule/W1R)+($ClassDateNumber + " week"))
   }
}

Anyway, unlike my suggested use of var, your method works. In suggesting using a var I’d overlooked my own notes:

It is a value reference - but not to an attribute.

As a result we can’t chain off a var. For example:

var X;
X = "cars";
$MyNumber = X.size;          // result is '0', oops!
$MyString = X;               // result is "cars"
$MyNumber = $MyString.size;  // result is '4'

So X holds a literal value but isn’t an object. You’d need to place its value in an actual attribute to use dot-functions on it. I should note Numeric vars do allow simple maths:

var Y(2);     // single line var declaration
$MyNumB = Y;  // result is 2
Y = Y * 4;
$MyNumC = Y;   // result is 8

Then again, the latter need—of caching values in attributes—was part of the genesis of the Sandbox group of attributes ($MyString, etc.) so you’ve at least one utility attribute of major types to hand avoiding the need to go make one. Over 16-odd years Tinderbox has got richer and more complex and one forgets…

I’ll alter my advice upthread re var use (so as to not mislead later readers).


(Andreas Grimm) #6

This looks interesting and likely what I’ve looking for myself lately.

However, may I kindly ask for an explanatory breakdown of:

$MyString=$Name(compositeFor(this):role(ClassDate));
if($MyString.size==3){
   if($MyString.contains("T")){
  $ClassDateNumber=eval($MyString.substr(1,1))-1;$StartDate=date($StartDate(/Schedule/W1T)+($ClassDateNumber + " week"))
   } else {
  $ClassDateNumber=eval($MyString.substr(1,1))-1;$StartDate=date($StartDate(/Schedule/W1R)+($ClassDateNumber + " week"))
   }
} else {
   if($MyString.contains("T")){
  $ClassDateNumber=eval($MyString.substr(1,2))-1;$StartDate=date($StartDate(/Schedule/W1T)+($ClassDateNumber + " week"))
   } else {
  $ClassDateNumber=eval($MyString.substr(1,2))-1;$StartDate=date($StartDate(/Schedule/W1R)+($ClassDateNumber + " week"))
   }
}

Maybe I could even ask for the respective conditionalRule.tbx you @mwra and @derekvan might have used as testdrive-doc to come up with the solution that eventually seems to work fine.


(Andreas Grimm) #7

After posting my previous post, I figured that this here may be just the right place to post my actual question which brought me here in the first place and which may not be as complex a conditional rule as the one discussed here so far.

So my question is:

Having two notes, I’d like the second note’s $StartDate being conditionally created and conditionally updated upon the first note’s $EndDate plus 14 days.

How do I do that?

Cheers!


(Mark Anderson) #8

$StartDate("Some other note") = date($EndDate + "14 days");

Tested in v7.3.1


(Andreas Grimm) #9

thanks. But I’m not certain about the “Some other note”-part

I changed it like so:

$StartDate= date($EndDate("Some other note") + "14 days");

It works for me this way.

But maybe there’s something to the solution you suggested, @mwra ,I didn’t catch.


(Mark Anderson) #10

My code assumed you wanted to use the $EndDate of the note currently with focus to set the $StartDate in a different note. The code you quoted was something complex from over a year ago so I didn’t have time to build a test rig and figure out what it was doing. So, ‘first note’ and ‘second note’ don’t explain much.

The basic points here is you can use a ‘offset’ reference, i.e. $StartDate("A note") vs. $StartDate, on the left side of the ‘=’ operator to set an offset value in a different note or on the right side to read an offset value from a different note.

Or is the problem that you’re unsure on date arithmetic?


(Andreas Grimm) #11

Now I see and your perfectly right @mwra. Thank you!