/**
* Data controller module
* @module app/DataController
* @author David Kristiansen <david.kristiansen@nscc.ca>
* @copyright Nova Scotia Community College 2017
*/
define([
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/on",
"dojo/topic",
"dojo/Evented",
"dojo/promise/all",
"dojo/request/xhr",
"esri/tasks/QueryTask",
"esri/tasks/query",
"dstore/Memory",
"dstore/Trackable",
"dojo/_base/array"
],
function (
declare,
lang,
on,
topic,
Evented,
all,
xhr,
QueryTask,
Query,
Memory,
Trackable,
arrayUtils
) {
return declare([Evented, Memory, Trackable], {
memDStore: {},
chartTrack: {},
stationList: {},
lcaList: {},
stationsIds: {},
/**
* Starts the module
*/
startup: function () {
// console.log("DataController::startup");
this._init();
},
/**
* Executes QueryTask https://developers.arcgis.com/javascript/3/jsapi/querytask-amd.html
* Need to use on("complete") and/or on("error") to get access to the response
* @param {string} urlQ URL of rest end point to be queried
* @param {array} outFieldsQ An optional array of fields to be returned (defaults to ["*"])
* @param {array} orderByQ An optional array of fields to order the results by (defaults to "")
* @param {boolean} geoQ Optional return geometry (defaults to false)
* @param {string} whereQ Optional where clause for a query (defaults to "1=1")
* @private
*
*/
_query: function (urlQ, outFieldsQ, orderByQ, geoQ, whereQ) {
if (outFieldsQ === undefined) {
outFieldsQ = ["*"];
}
if (orderByQ === undefined) {
orderByQ = "";
}
if (geoQ === undefined) {
geoQ = false;
}
if (whereQ === undefined) {
whereQ = "1=1";
}
var QT = new QueryTask(urlQ);
var Q = new Query();
Q.returnGeometry = geoQ;
Q.outFields = outFieldsQ;
Q.orderByFields = orderByQ;
Q.where = whereQ;
return QT.execute(Q);
},
/**
* Converts initial query task results of tide stations and lidar coverage areas into
* dstore memory stores
* @param {obj} fs feature set results from query task
* @private
*
**/
_getStarted: function (fs) {
/** @function mapStnIds
* @description Swaps keys and values of tide station
* @param {obj} query task results
**/
function mapStnIds(result) {
var swappedResults = {};
var stns = result.tables;
for (var i = 0; i < stns.length; i++) {
swappedResults[stns[i].name] = stns[i].id;
}
return swappedResults;
}
/**
* @function toTitleCase
* @description Converts strings to title case.
* Modified from http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript
* @param {string} str The text to be converted to titleCase.
**/
function toTitleCase(str) {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
var tideResults, stnResults, lcaResults;
// make sure both queries finished successfully
if (!fs[0].hasOwnProperty("features")) {
console.error("One query failed.");
}
if (!fs[1].hasOwnProperty("features")) {
console.error("Two query failed.");
}
if (!fs[2].hasOwnProperty("tables")) {
console.error("Three query failed.");
}
lcaResults = fs[0].features;
stnResults = fs[1].features;
tideResults = fs[2];
this.stationList = new Memory({
data: arrayUtils.map(stnResults, function (f) {
return {
"site_id": f.attributes.site_id,
"stn_id": f.attributes.stn_id,
"name": toTitleCase(f.attributes.stn_name)
};
}),
idProperty: "site_id"
});
this.lcaList = new Memory({
data: arrayUtils.map(lcaResults, function (f) {
return {
"said": f.attributes.said,
"default_site_id": f.attributes.default_site_id,
"name": f.attributes.name
};
}),
idProperty: "said"
});
this.stationsIds = mapStnIds(tideResults);
this.emit("load", {});
},
/**
* Processes feature set from query task of storm surge and tide data for a particular tide station.
* Creates/overwrites a dstore memory stores used with the tide and storm surge chart.
* @param {obj} fs feature set results from query task
* @private
*
**/
_prepData: function (fs) {
// console.log("Tide queries finished: ", fs);
var tideResults;
// make sure both queries finished successfully
if (!fs.hasOwnProperty("features")) {
console.error("Tide query failed.");
return;
}
tideResults = fs.features;
this.memDStore = new(declare([Memory, Trackable]))({
data: arrayUtils.map(tideResults, function (f) {
return {
"fulldate": f.attributes.dt,
"tide": f.attributes.tide,
"surge": f.attributes.surge,
"twl": f.attributes.twl
};
}),
idProperty: "fulldate"
});
this.chartTrack = new(declare([Memory, Trackable]))({
data: arrayUtils.map(tideResults, function (f) {
return {
"dt": f.attributes.dt,
"now": 0,
"sel": 0,
"clk": 1
};
}),
idProperty: "dt"
});
// console.log("DataController::tideData_ready");
this.emit("tideData_ready", {});
},
/**
* Private method that initializes the module by querying for the lidar coverage areas and tide stations.
* Waits both queries to complete before continuing.
* @private
*
*/
_init: function () {
var lca = this._query("//agrgims.cogs.nscc.ca/arcgis/rest/services/mcfm_pro/sa_flood/MapServer/0", ["said", "default_site_id", "default_site_id", "name"], ["name"]);
var stations = this._query("//agrgims.cogs.nscc.ca/arcgis/rest/services/mcfm_pro/tide_stns/MapServer/0", ["site_id", "stn_id", "stn_name"], ["stn_name"]);
var stationIds = this._getStationsIds();
var promises = all([lca, stations, stationIds]);
promises.then(lang.hitch(this, this._getStarted));
// console.log("Created dd list");
},
/**
* Queries url for tide and storm surge data for a particular tide station.
* Passes results to _prepData method to format data into a dstore memory store
* @param {string} dataURL URL of rest end point to be queried
* @public
*
**/
getTideData: function (dataURL) {
var data = this._query(dataURL, ["dt", "tide", "surge", "twl"], ["dt"]); //need to add order by to get the data into order!!
data.then(lang.hitch(this, this._prepData));
},
/**
* Json request to get the list of tide stations
* @private
*
**/
_getStationsIds: function () {
return xhr("//agrgims.cogs.nscc.ca/arcgis/rest/services/mcfm_pro/tide_stns/MapServer?f=pjson", {
handleAs: "json",
headers: {
"X-Requested-With": null
}
});
}
});
});