In the final part of this mini-series, Intelligent-Advisor.com continues to look at Temporal Reasoning and in this particular chapter discusses the display of Temporal Attributes data in the Interview experience.
If you missed any of the previous parts of the series, they are here:
- Part One : Introduction
- Part Two : ValueAt Function
- Part Three : Interval Functions
- Part Four : Converting to-and-from Temporal Values
So now that the we have a bit of understanding of how these data elements work, what about displaying them in a good way to the end user in the Interview. Well, part of the answer is hidden in part four of this series. We cannot actually display temporal attributes for data entry in an Interview (so conversion comes in very handy).
Let’s be more specific. Using the project from the previous chapter, in 18C, when an attempt is made to display the temporal information on a Screen, various things happen that underline the some important concepts:
Please excuse the retro-style animated GIF above. But the demonstration above illustrates the fact that Temporal attributes and their change-points are complex data types that cannot be handled in a “normal” way. The one exception to the above is if you have a Temporal attribute whose values are the Goal of the interview, then an Explanation will display the data in a coherent way:
If your project is using RuleScript and your data is pre-seeded, then potentially you could access it by deriving a string value which is a concatenation of the different values and displaying that attribute using a label control.
// RuleScript(myString) <- (temporalBankBalance)
function FindHighest(global) {
console.log("Starting RuleScript");
var v = global.temporalBankBalance;
console.log("Base Value of v " + v._baseValue);
var idx,
maxVal = null;
var myString = "";
console.log("Length of Temporal Array " + v._changeValues.length);
if (v._changeValues.length <= 0) {
global.myString = "No Temporal Values";
} else {
console.log("Getting Temporal Values");
for (idx = 0; idx < v._changeValues.length; idx++) { var changeValue = v._changeValues.valueAt(idx); if (changeValue != null && (maxVal == null || changeValue > maxVal))
maxVal = changeValue;
}
global.myString = global.myString + changeValue + ";";
}
}
But given that RuleScript is experimental, that it’s use cases are highly controlled this would be a very risky idea. Plus it would only work if the temporal values were pre-seeded into the Interview, which renders it all very complex.
So what is plan B? It might be to use something like the Entity Container Extension that we have previously looked at (which would imply using the conversion technique mentioned in part four).
If you are looking for a quick and dirty way to get at the Temporal values, even though the JavaScript Extensions do not actually support them today, the values are still accessible. They can be accessed using something like this. I have not published this as a download since the snippet below is very primitive.
/**
* intelligent-advisor.com
* Educational Example of Custom Container with a Timeline inside
* I will remember this is for demonstration and educational purposes only
*/
OraclePolicyAutomation.AddExtension({
customLabel: function (control, interview) {
if (control.getProperty("name") === "xTimeline") {
return {
mount: function (el) {
var script_tag_addition = document.createElement('script');
script_tag_addition.setAttribute('src', '${resources-root}/js/timeline.min.js');
script_tag_addition.setAttribute('type', 'text/javascript');
document.getElementsByTagName('head')[0].appendChild(script_tag_addition);
var stylesheet_tag_addition = document.createElement('link');
stylesheet_tag_addition.setAttribute('href', '${resources-root}/css/timeline.min.css');
stylesheet_tag_addition.setAttribute('rel', 'stylesheet');
stylesheet_tag_addition.setAttribute('type', 'text/css');
document.getElementsByTagName('head')[0].appendChild(stylesheet_tag_addition);
var myDiv = document.createElement("div");
myDiv.setAttribute("class", "timeline");
myDiv.setAttribute("data-mode", "horizontal");
el.appendChild(myDiv);
var myDivWrap = document.createElement("div");
myDivWrap.setAttribute("class", "timeline__wrap");
$(".timeline").append(myDivWrap);
var myDivChild = document.createElement("div");
myDivChild.setAttribute("class", "timeline__items");
$(".timeline__wrap").append(myDivChild);
// Don't do this, it relies upon the temporal attribute
// being the only one in Global exposed on the page as a %label%
var myTemporal = []
myTemporal = control._source.screen.config.data[0].instances[0].attributes[0].value.changePoints
for (var i in myTemporal) {
var iterateDIV = document.createElement("div");
iterateDIV.setAttribute("class", "timeline__item");
iterateDIV.setAttribute("id", i);
$(".timeline__items").append(iterateDIV)
var iterateDIVContent = document.createElement("div");
iterateDIVContent.setAttribute("class", "timeline__content");
$('.timeline__item[id="' + i + '"]').append( "GBP " + myTemporal[i].value + " on " + myTemporal[i].date)
}
},
update: function (el) {},
unmount: function (el) {
var myDiv = $(".timeline");
myDiv.remove();
}
}
}
}
});
The above snippet relies upon a jQuery plugin to display the data. This gives something like this, a visual timeline on the left of this page:
Of course there are hundreds of Timeline plugins, each more sophisticated than the other, on the Internet.
We hope that this series has brought to light some of the key features of temporal reasoning, and thanks to long-time reader ORO who suggested this series in the first place.
Thanks for reading and see you soon! If you want to formalize your Temporal Reasoning learning experience, check out our new Oracle Intelligent Advisor – Introduction to Temporal Reasoning Course.