Here is a better version of the last template program. The original was throwing exceptions that didn't hurt anything but cluttered up the log. This one avoids that by ensuring that only numbers are passed to the cmp function.
Code:
program:
comments = field('comments');
percent = re(comments, '(?is).*last page read: location \d+ \((\d+)%\).*', '\1');
contains( comments,
'(?i).*?last page read: location',
cmp(switch(percent, '^\d*$', percent, 0),
94,
'No',
'No',
'Yes'),
'Unopened')