/*global define */
define(['jquery', 'underscore', 'backbone'],
function($, _, Backbone) {
'use strict';
/**
* @class Metrics
* @classdesc A single result from the DataONE Metrics Service
* @classcategory Models
* @extends Backbone.Model
* @constructor
*/
var Metrics = Backbone.Model.extend(
/** @lends Metrics.prototype */{
/**
* The name of this Model
* @type {string}
*/
type: "Metrics",
defaults: {
metricRequest: null,
startDate: null,
endDate: null,
results: null,
resultDetails: null,
pid_list: null,
url: null,
filterType: null,
// metrics and metric Facets returned as response from the user
// datatype: array
citations: null,
views: null,
downloads: null,
months: null,
country: null,
years: null,
repository: null,
award: null,
datasets: null,
// Total counts for metrics
totalCitations: null,
totalViews: null,
totalDownloads: null,
// flag to send POST request to the metrics service
useMetricsPost: false,
// colelctionQuery for Portal Objects
filterQueryObject: null,
forwardCollectionQuery: false,
metricsRequiredFields: {
metricName: true,
pid_list: true
}
},
metricRequest: {
"metricsPage": {
"total": 0,
"start": 0,
"count": 0
},
"metrics": [
"citations",
"downloads",
"views"
],
"filterBy": [
{
"filterType": "",
"values": [],
"interpretAs": "list"
},
{
"filterType": "month",
"values": [],
"interpretAs": "range"
}
],
"groupBy": [
"month"
]
},
/**
* Initializing the Model objects pid and the metricName variables.
* @param {object} options
*/
initialize: function(options) {
if((options) && options.pid_list !== 'undefined') {
this.set("pid_list", options.pid_list);
this.set("filterType", options.type);
}
this.set("startDate", "01/01/2012");
// overwrite forwardCollectionQuery flag
this.set("forwardCollectionQuery", MetacatUI.appModel.get("metricsForwardCollectionQuery"));
// url for the model that is used to for the fetch() call
this.url = MetacatUI.appModel.get("metricsUrl");
},
/**
* Overriding the Model's fetch function.
*/
fetch: function(){
var fetchOptions = {};
this.metricRequest.filterBy[0].filterType = this.get("filterType");
this.metricRequest.filterBy[0].values = this.get("pid_list");
// TODO: Set the startDate and endDate based on the datePublished and current date
// respctively.
this.metricRequest.filterBy[1].values = [];
this.metricRequest.filterBy[1].values.push(this.get("startDate"));
this.metricRequest.filterBy[1].values.push(this.getCurrentDate());
// set custom request settings if we're forwarding a CollectionQuery for a portal
if ( this.get("forwardCollectionQuery") && this.get("filterType") === "portal"
&& this.get("filterQueryObject") != undefined
&& typeof this.get("filterQueryObject") === "object") {
var filterQueryObject = this.get("filterQueryObject");
if (filterQueryObject.filterType != undefined
&& filterQueryObject.filterType == "query") {
if (Array.isArray(filterQueryObject.values)
&& filterQueryObject.values.length > 0 ) {
// check if query object exists
var queryInserted = this.metricRequest.filterBy.indexOf(filterQueryObject);
// Performing HTTP POST?
if(this.get("useMetricsPost")) {
// insert query object
if (queryInserted < 0) {
this.metricRequest.filterBy.push(filterQueryObject);
}
fetchOptions = _.extend({
data:JSON.stringify(this.metricRequest),
type:"POST",
timeout:300000
});
}
else {
// insert query object
var collectionQuery = filterQueryObject.values[0];
if (collectionQuery.length < 1000 && queryInserted < 0) {
this.metricRequest.filterBy.push(filterQueryObject);
}
// set the fetch options for
var model = this;
fetchOptions = _.extend({
data:"metricsRequest="+JSON.stringify(this.metricRequest),
timeout:300000,
// on error recursively call fetch, but this time use POST
error: function(response){
model.set("useMetricsPost", "true");
model.fetch();
}
});
}
}
}
}
// check if we need to set fetchOptions
if (Object.keys(fetchOptions).length === 0) {
if ( this.get("useMetricsPost") ) {
fetchOptions = _.extend({
data:JSON.stringify(this.metricRequest),
type:"POST",
timeout:300000
});
}
else {
fetchOptions = _.extend({
data:"metricsRequest="+JSON.stringify(this.metricRequest),
timeout:300000,
});
}
}
//This calls the Backbone fetch() function but with our custom fetch options.
return Backbone.Model.prototype.fetch.call(this, fetchOptions);
},
/**
* Get's a string version of today's date
* @return {string}
*/
getCurrentDate: function() {
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();
if(dd<10){
dd='0'+dd;
}
if(mm<10){
mm='0'+mm;
}
var today = mm+'/'+dd+'/'+yyyy;
return today;
},
/**
* Parsing the response for setting the Model's member variables.
*/
parse: function(response){
var metricsObject = {
"metricRequest": response.metricsRequest,
"citations": response.results.citations,
"views": response.results.views,
"downloads": response.results.downloads,
"months": response.results.months,
"country": response.results.country,
"resultDetails": response.resultDetails,
"datasets": response.results.datasets
}
if (response.results.citations != null) {
metricsObject["totalCitations"] = response.results.citations.reduce(function(acc, val) { return acc + val; }, 0)
}
else {
metricsObject["totalCitations"] = 0
}
if (response.results.downloads != null) {
metricsObject["totalDownloads"] = response.results.downloads.reduce(function(acc, val) { return acc + val; }, 0)
}
else {
metricsObject["totalDownloads"] = 0
}
if (response.results.views != null) {
metricsObject["totalViews"] = response.results.views.reduce(function(acc, val) { return acc + val; }, 0)
}
else {
metricsObject["totalViews"] = 0
}
//trim off the leading zeros and their corresponding months
if (response.results.months != null) {
// iterate all the metrics objects and remove the entry if the counts are 0
for (var i = 0 ; i < metricsObject["months"].length; i++) {
if ( metricsObject["citations"] != null &&
metricsObject["views"] != null &&
metricsObject["downloads"] != null ) {
if (( metricsObject["citations"][i] == 0 ) &&
( metricsObject["views"][i] == 0 ) &&
( metricsObject["downloads"][i] == 0 )) {
metricsObject["months"].splice(i,1);
metricsObject["citations"].splice(i,1);
metricsObject["views"].splice(i,1);
metricsObject["downloads"].splice(i,1);
// if country facet was part of the request; update object;
if ( metricsObject["country"] != null) {
metricsObject["country"].splice(i,1)
}
// modified array size; decrement the counter;
i--;
}
else {
break;
}
}
}
}
return metricsObject;
},
});
return Metrics;
});