diff --git a/dist/datamodel.js b/dist/datamodel.js index b3d929a..f805aba 100644 --- a/dist/datamodel.js +++ b/dist/datamodel.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("DataModel",[],t):"object"==typeof exports?exports.DataModel=t():e.DataModel=t()}(window,function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e){e.exports={name:"datamodel",description:"Relational algebra compliant in-memory tabular data store",homepage:"https://github.com/chartshq/datamodel",version:"2.2.1",license:"MIT",main:"dist/datamodel.js",keywords:["datamodel","data","relational","algebra","model","muze","fusioncharts","table","tabular","operation"],author:"Muzejs.org (https://muzejs.org/)",repository:{type:"git",url:"https://github.com/chartshq/datamodel.git"},contributors:[{name:"Akash Goswami",email:"akashgoswami90s@gmail.com"},{name:"Subhash Haldar"},{name:"Rousan Ali",email:"rousanali786@gmail.com",url:"https://rousan.io"},{name:"Ujjal Kumar Dutta",email:"duttaujjalkumar@live.com"}],dependencies:{"d3-dsv":"^1.0.8"},devDependencies:{"babel-cli":"6.26.0","babel-core":"^6.26.3","babel-eslint":"6.1.2","babel-loader":"^7.1.4","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.7.0","babel-preset-es2015":"^6.24.1","babel-preset-flow":"^6.23.0",chai:"3.5.0","cross-env":"^5.0.5",eslint:"3.19.0","eslint-config-airbnb":"15.1.0","eslint-plugin-import":"2.7.0","eslint-plugin-jsx-a11y":"5.1.1","eslint-plugin-react":"7.3.0","istanbul-instrumenter-loader":"^3.0.0",jsdoc:"3.5.5",json2yaml:"^1.1.0",karma:"1.7.1","karma-chai":"0.1.0","karma-chrome-launcher":"2.1.1","karma-coverage-istanbul-reporter":"^1.3.0","karma-mocha":"1.3.0","karma-spec-reporter":"0.0.31","karma-webpack":"2.0.3",marked:"^0.5.0",mocha:"3.4.2","mocha-webpack":"0.7.0","transform-runtime":"0.0.0",webpack:"^4.12.0","webpack-cli":"^3.0.7","webpack-dev-server":"^3.1.4"},scripts:{test:"npm run lint && npm run ut",ut:"karma start karma.conf.js",utd:"karma start --single-run false --browsers Chrome karma.conf.js ",build:"npm run build:prod","build:dev":"webpack --mode development","build:prod":"webpack --mode production",start:"webpack-dev-server --config webpack.config.dev.js --mode development --open",lint:"eslint ./src","lint-errors":"eslint --quiet ./src",docs:"rm -rf yaml && mkdir yaml && jsdoc -c jsdoc.conf.json"}}},function(e,t,n){var r=n(2);e.exports=r.default?r.default:r},function(e,t,n){"use strict";n.r(t);var r={};n.r(r),n.d(r,"DataFormat",function(){return o}),n.d(r,"DimensionSubtype",function(){return u}),n.d(r,"MeasureSubtype",function(){return c}),n.d(r,"FieldType",function(){return f}),n.d(r,"FilteringMode",function(){return l}),n.d(r,"GROUP_BY_FUNCTIONS",function(){return s});var a={};n.r(a),n.d(a,"DSVArr",function(){return Ze}),n.d(a,"DSVStr",function(){return lt}),n.d(a,"FlatJSON",function(){return st}),n.d(a,"Auto",function(){return pt});var i={};n.r(i),n.d(i,"sum",function(){return Jt}),n.d(i,"avg",function(){return zt}),n.d(i,"min",function(){return Kt}),n.d(i,"max",function(){return Wt}),n.d(i,"first",function(){return Xt}),n.d(i,"last",function(){return qt}),n.d(i,"count",function(){return Zt}),n.d(i,"sd",function(){return $t});var o={FLAT_JSON:"FlatJSON",DSV_STR:"DSVStr",DSV_ARR:"DSVArr",AUTO:"Auto"},u={CATEGORICAL:"categorical",TEMPORAL:"temporal",GEO:"geo",BINNED:"binned"},c={CONTINUOUS:"continuous"},f={MEASURE:"measure",DIMENSION:"dimension"},l={NORMAL:"normal",INVERSE:"inverse",ALL:"all"},s={SUM:"sum",AVG:"avg",MIN:"min",MAX:"max",FIRST:"first",LAST:"last",COUNT:"count",STD:"std"};function d(e){return e instanceof Date?e:new Date(e)}function p(e){return e<10?"0"+e:e}function h(e){this.format=e,this.dtParams=void 0,this.nativeDate=void 0}RegExp.escape=function(e){return e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},h.TOKEN_PREFIX="%",h.DATETIME_PARAM_SEQUENCE={YEAR:0,MONTH:1,DAY:2,HOUR:3,MINUTE:4,SECOND:5,MILLISECOND:6},h.defaultNumberParser=function(e){return function(t){var n;return isFinite(n=parseInt(t,10))?n:e}},h.defaultRangeParser=function(e,t){return function(n){var r,a=void 0;if(!n)return t;var i=n.toLowerCase();for(a=0,r=e.length;aa.getFullYear()&&(t=""+(i-1)+r),d(t).getFullYear()},formatter:function(e){var t=d(e).getFullYear().toString(),n=void 0;return t&&(n=t.length,t=t.substring(n-2,n)),t}},Y:{name:"Y",index:0,extract:function(){return"(\\d{4})"},parser:h.defaultNumberParser(),formatter:function(e){return d(e).getFullYear().toString()}}}},h.getTokenFormalNames=function(){var e=h.getTokenDefinitions();return{HOUR:e.H,HOUR_12:e.l,AMPM_UPPERCASE:e.p,AMPM_LOWERCASE:e.P,MINUTE:e.M,SECOND:e.S,SHORT_DAY:e.a,LONG_DAY:e.A,DAY_OF_MONTH:e.e,DAY_OF_MONTH_CONSTANT_WIDTH:e.d,SHORT_MONTH:e.b,LONG_MONTH:e.B,MONTH_OF_YEAR:e.m,SHORT_YEAR:e.y,LONG_YEAR:e.Y}},h.tokenResolver=function(){var e=h.getTokenDefinitions(),t=function(){for(var e=0,t=void 0,n=void 0,r=arguments.length;e=0;)o=e[i+1],-1!==r.indexOf(o)&&a.push({index:i,token:o});return a},h.formatAs=function(e,t){var n,r=d(e),a=h.findTokens(t),i=h.getTokenDefinitions(),o=String(t),u=h.TOKEN_PREFIX,c=void 0,f=void 0,l=void 0;for(l=0,n=a.length;l=0;d--)(f=i[d].index)+1!==s.length-1?(void 0===u&&(u=s.length),l=s.substring(f+2,u),s=s.substring(0,f+2)+RegExp.escape(l)+s.substring(u,s.length),u=f):u=f;for(d=0;d0&&e.split(",").forEach(function(e){var n=e.split("-"),r=+n[0],a=+(n[1]||n[0]);if(a>=r)for(var i=r;i<=a;i+=1)t(i)})}var R=function(){function e(e,t){for(var n=0;n=(i=e[a=n+Math.floor((r-n)/2)]).start&&t=i.end?n=a+1:t3&&void 0!==arguments[3]&&arguments[3],a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:L.CROSS,i=[],o=[],u=n||H,c=e.getFieldspace(),f=t.getFieldspace(),l=c.name,s=f.name,d=c.name+"."+f.name,p=B(c,f);if(l===s)throw new Error("DataModels must have different alias names");return c.fields.forEach(function(e){var t=_({},e.schema());-1===p.indexOf(t.name)||r||(t.name=c.name+"."+t.name),i.push(t)}),f.fields.forEach(function(e){var t=_({},e.schema());-1!==p.indexOf(t.name)?r||(t.name=f.name+"."+t.name,i.push(t)):i.push(t)}),T(e._rowDiffset,function(n){var d=!1,h=void 0;T(t._rowDiffset,function(v){var m=[],y={};y[l]={},y[s]={},c.fields.forEach(function(e){m.push(e.partialField.data[n]),y[l][e.name()]=e.partialField.data[n]}),f.fields.forEach(function(e){-1!==p.indexOf(e.schema().name)&&r||m.push(e.partialField.data[v]),y[s][e.name()]=e.partialField.data[v]});var g=gt(y[l]),b=gt(y[s]);if(u(g,b,function(){return e.detachedRoot()},function(){return t.detachedRoot()},{})){var w={};m.forEach(function(e,t){w[i[t].name]=e}),d&&L.CROSS!==a?o[h]=w:(o.push(w),d=!0,h=n)}else if((a===L.LEFTOUTER||a===L.RIGHTOUTER)&&!d){var O={},_=c.fields.length-1;m.forEach(function(e,t){O[i[t].name]=t<=_?e:null}),d=!0,h=n,o.push(O)}})}),new Gt(o,i,{name:d})}function J(e,t){var n=""+e,r=""+t;return nr?1:0}function z(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:J;return e.length>1&&function e(t,n,r,a){if(r===n)return t;var i=n+Math.floor((r-n)/2);return e(t,n,i,a),e(t,i+1,r,a),function(e,t,n,r,a){for(var i=e,o=[],u=t;u<=r;u+=1)o[u]=i[u];for(var c=t,f=n+1,l=t;l<=r;l+=1)c>n?(i[l]=o[f],f+=1):f>r?(i[l]=o[c],c+=1):a(o[c],o[f])<=0?(i[l]=o[c],c+=1):(i[l]=o[f],f+=1)}(t,n,i,r,a),t}(e,0,e.length-1,t),e}function K(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ti?"desc"===t?-1:1:0}}return r}function X(e,t){var n=new Map,r=[];return e.forEach(function(e){var a=e[t];n.has(a)?r[n.get(a)][1].push(e):(r.push([a,[e]]),n.set(a,r.length-1))}),r}function q(e,t,n){var r={label:e[0]};return t.reduce(function(t,r,a){return t[r]=e[1].map(function(e){return e[n[a].index]}),t},r),r}function Z(e,t,n,r,a){a=Object.assign({},{addUid:!1,columnWise:!1},a);var i={schema:[],data:[],uids:[]},o=a.addUid,u=r&&r.length>0,c=[];if(n.split(",").forEach(function(t){for(var n=0;n=0;u--)a=t[u][0],i=t[u][1],(o=Ct(r,a))&&("function"==typeof i?z(n,function(e,t){return i(e[o.index],t[o.index])}):E(i)?function(){var e=X(n,o.index),t=i[i.length-1],a=i.slice(0,i.length-1),u=a.map(function(e){return Ct(r,e)});e.forEach(function(e){e.push(q(e,a,u))}),z(e,function(e,n){var r=e[2],a=n[2];return t(r,a)}),n.length=0,e.forEach(function(e){n.push.apply(n,K(e[1]))})}():(i="desc"===String(i).toLowerCase()?"desc":"asc",z(n,W(o.type,i,o.index))));e.uids=[],n.forEach(function(t){e.uids.push(t.pop())})}(i,r),a.columnWise){var f=Array.apply(void 0,K(Array(i.schema.length))).map(function(){return[]});i.data.forEach(function(e){e.forEach(function(e,t){f[t].push(e)})}),i.data=f}return i}function $(e,t){var n={},r=[],a=[],i=[],o=e.getFieldspace(),u=t.getFieldspace(),c=o.fieldsObj(),f=u.fieldsObj(),l=o.name+" union "+u.name;if(!j(e._colIdentifier.split(",").sort(),t._colIdentifier.split(",").sort()))return null;function s(e,t,r){T(e._rowDiffset,function(e){var o={},u="";a.forEach(function(n){var r=t[n].partialField.data[e];u+="-"+r,o[n]=r}),n[u]||(r&&i.push(o),n[u]=!0)})}return e._colIdentifier.split(",").forEach(function(e){var t=c[e];r.push(_({},t.schema())),a.push(t.schema().name)}),s(t,f,!1),s(e,c,!0),new Gt(i,r,{name:l})}function Q(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ee(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t1&&void 0!==arguments[1]?arguments[1]:{},n={},r=e.getFieldspace().getMeasure(),a=me.defaultReducer();return Object.keys(r).forEach(function(e){"string"!=typeof t[e]&&(t[e]=r[e].defAggFn());var i=me.resolve(t[e]);i?n[e]=i:(n[e]=a,t[e]=pe)}),n}(e,n),o=e.getFieldspace(),u=o.fieldsObj(),c=o.name,l=[],s=[],d=[],p={},h=[],v=void 0;Object.entries(u).forEach(function(e){var t=ye(e,2),n=t[0],r=t[1];if(-1!==a.indexOf(n)||i[n])switch(d.push(_({},r.schema())),r.schema().type){case f.MEASURE:s.push(n);break;default:case f.DIMENSION:l.push(n)}});var m=0;T(e._rowDiffset,function(e){var t="";l.forEach(function(n){t=t+"-"+u[n].partialField.data[e]}),void 0===p[t]?(p[t]=m,h.push({}),l.forEach(function(t){h[m][t]=u[t].partialField.data[e]}),s.forEach(function(t){h[m][t]=[u[t].partialField.data[e]]}),m+=1):s.forEach(function(n){h[p[t]][n].push(u[n].partialField.data[e])})});var y={},g=function(){return e.detachedRoot()};return h.forEach(function(e){var t=e;s.forEach(function(n){t[n]=i[n](e[n],g,y)})}),r?(r.__calculateFieldspace(),v=r):v=new tn(h,d,{name:c}),v}function be(e,t){var n=B(e.getFieldspace(),t.getFieldspace());return function(e,t){var r=!0;return n.forEach(function(n){r=!(e[n].value!==t[n].value||!r)}),r}}function we(e,t){var n={},r=[],a=[],i=[],o=e.getFieldspace(),u=t.getFieldspace(),c=o.fieldsObj(),f=u.fieldsObj(),l=o.name+" union "+u.name;if(!j(e._colIdentifier.split(",").sort(),t._colIdentifier.split(",").sort()))return null;function s(e,t){T(e._rowDiffset,function(e){var r={},o="";a.forEach(function(n){var a=t[n].partialField.data[e];o+="-"+a,r[n]=a}),n[o]||(i.push(r),n[o]=!0)})}return e._colIdentifier.split(",").forEach(function(e){var t=c[e];r.push(_({},t.schema())),a.push(t.schema().name)}),s(e,c),s(t,f),new tn(i,r,{name:l})}function Oe(e,t,n){return G(e,t,n,!1,L.LEFTOUTER)}function _e(e,t,n){return G(t,e,n,!1,L.RIGHTOUTER)}var Ee=function(){function e(e,t){for(var n=0;nn&&(n=a))}),[t,n]}}]),t}(),xe=function(){function e(e,t){for(var n=0;n9999?"+"+it(t,6):it(t,4))+"-"+it(e.getUTCMonth()+1,2)+"-"+it(e.getUTCDate(),2)+(i?"T"+it(n,2)+":"+it(r,2)+":"+it(a,2)+"."+it(i,3)+"Z":a?"T"+it(n,2)+":"+it(r,2)+":"+it(a,2)+"Z":r||n?"T"+it(n,2)+":"+it(r,2)+"Z":"")}var ut=function(e){var t=new RegExp('["'+e+"\n\r]"),n=e.charCodeAt(0);function r(e,t){var r,a=[],i=e.length,o=0,u=0,c=i<=0,f=!1;function l(){if(c)return Qe;if(f)return f=!1,$e;var t,r,a=o;if(e.charCodeAt(a)===et){for(;o++=i?c=!0:(r=e.charCodeAt(o++))===tt?f=!0:r===nt&&(f=!0,e.charCodeAt(o)===tt&&++o),e.slice(a+1,t-1).replace(/""/g,'"')}for(;o2&&void 0!==arguments[2]?arguments[2]:{},a=arguments[3];t===U.COMPOSE?(e._derivation.length=0,(n=e._derivation).push.apply(n,mt(a))):e._derivation.push({op:t,meta:r,criteria:a})}(t,n,arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},arguments[4]),function(e,t){var n;(n=t._ancestorDerivation).push.apply(n,mt(e._ancestorDerivation).concat(mt(e._derivation)))}(e,t)},Ot=(vt(dt={},l.NORMAL,{diffIndex:["rowDiffset"],calcDiff:[!0,!1]}),vt(dt,l.INVERSE,{diffIndex:["rejectRowDiffset"],calcDiff:[!1,!0]}),vt(dt,l.ALL,{diffIndex:["rowDiffset","rejectRowDiffset"],calcDiff:[!0,!0]}),dt),_t=function(e,t,n){if(-1!==n&&t===n+1){var r=e.length-1;e[r]=e[r].split("-")[0]+"-"+t}else e.push(""+t)},Et=function(e,t,n){var r=[],a=[],i=ht(Ot[n].calcDiff,2),o=i[0],u=i[1];return T(e,function(e){var n=t(e);n&&o&&_t(r,e,-1),!n&&u&&_t(a,e,-1)}),{rowDiffset:r.join(","),rejectRowDiffset:a.join(",")}},At=function(e,t,n,r,a){var i={},o=function(){return r.detachedRoot()},u=n.mode,c=e._rowDiffset,f=e.getPartialFieldspace().fields;return a(c,function(e){return t(yt(f,e),e,o,i)},u)},jt=function(e,t,n){for(var r=n(e,t,0),a=1,i=e.length;a2&&void 0!==arguments[2]?arguments[2]:{},r=[],a=n.operation||V,i=n.filterByMeasure||!1,o=function(e){var t=e.clone(!1),n=e.getPartialFieldspace();return t._colIdentifier=n.fields.map(function(e){return e.name()}).join(","),n._cachedFieldsObj=null,n._cachedDimension=null,n._cachedMeasure=null,t.__calculateFieldspace().calculateFieldsConfig(),t}(e),u=o.getFieldsConfig();r=t.length?t.map(function(e){return n=void 0,r=(t=e).getData(),a=t.getFieldsConfig(),o=Object.keys(t.getFieldspace().getDimension()).filter(function(e){return e in u}),c=o.length,f=o.map(function(e){return a[e].index}),l=Object.keys(t.getFieldspace().getMeasure()).filter(function(e){return e in u}),s=t.getFieldspace().fieldsObj(),d=r.data,p=l.reduce(function(e,t){return e[t]=s[t].domain(),e},{}),h={},n=function(e,t,n){return t[e[n]]},c&&d.forEach(function(e){var t=jt(f,e,n);h[t]=1}),n=function(e,t,n){return t[e[n]].value},d.length?function(e){var t=!c||h[jt(o,e,n)];return i?l.every(function(t){return e[t].value>=p[t][0]&&e[t].value<=p[t][1]})&&t:t}:function(){return!1};var t,n,r,a,o,c,f,l,s,d,p,h}):[function(){return!1}];return a===V?o.select(function(e){return r.every(function(t){return t(e)})},{saveChild:!1}):o.select(function(e){return r.some(function(t){return t(e)})},{saveChild:!1})},Dt=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(e){return e},r=arguments[3],a=r.saveChild,i=e.getFieldspace().fieldsObj(),o=At(e.clone(a),n,r,e,function(){for(var e=arguments.length,n=Array(e),r=0;r2&&void 0!==arguments[2]?arguments[2]:{},a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},i=a.nonTraversingModel,o=a.excludeModels||[];t!==i&&((!o.length||-1===o.indexOf(t))&&t.handlePropagation(n,r),t._children.forEach(function(t){var i=Mt(n,t);e(t,i,r,a)}))},It=function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];e._parent;)t.push(e),e=e._parent;return t},xt=function(e,t,n,r){var a=void 0,i=void 0,o=n.propagationNameSpace,u=n.propagateToSource,c=n.sourceId,f=r.propagateInterpolatedValues,l=[];if(null===e&&!0!==r.persistent)l=[{criteria:[]}],a=[];else{var s,d=Object.values(o.mutableActions);!1!==u&&(d=d.filter(function(e){return e.config.sourceId!==c}));var p=d.filter(function(e){return(r.filterFn||function(){return!0})(e,r)}).map(function(e){return e.config.criteria}),h=[];if(!1!==u){var v=Object.values(o.mutableActions);v.forEach(function(e){var t=e.config;!1===t.applyOnSource&&t.action===r.action&&t.sourceId!==c&&(h.push(e.model),(a=v.filter(function(t){return t!==e}).map(function(e){return e.config.criteria})).length&&l.push({criteria:a,models:e.model,path:It(e.model)}))})}a=(s=[]).concat.apply(s,[].concat(mt(p),[e])).filter(function(e){return null!==e}),l.push({criteria:a,excludeModels:[].concat(h,mt(r.excludeModels||[]))})}var m=t.model,y=Object.assign({sourceIdentifiers:e,propagationSourceId:c},r),g=t.groupByModel;f&&g&&(i=St(g,a,{filterByMeasure:f}),Pt(g,i,y)),l.forEach(function(e){var t=St(m,e.criteria),n=e.path;if(n){var r=function(e,t){for(var n=0,r=t.length;n1?(a=e.clone(r.saveChild),Ft(a,u[c[1]],e,n,t),[o,a]):o}(this,e,t,{saveChild:t.saveChild})}},{key:"isEmpty",value:function(){return!this._rowDiffset.length||!this._colIdentifier.length}},{key:"clone",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=new this.constructor(this);return e?t.setParent(this):t.setParent(null),t}},{key:"project",value:function(e,t){var n={mode:l.NORMAL,saveChild:!0};t=Object.assign({},n,t);var r=this.getFieldsConfig(),a=Object.keys(r),i=t.mode,o=Ut(e,a,r),u=void 0;i===l.ALL?u=[Nt(this,o,{mode:l.NORMAL,saveChild:t.saveChild},a),Nt(this,o,{mode:l.INVERSE,saveChild:t.saveChild},a)]:u=Nt(this,o,t,a);return u}},{key:"getFieldsConfig",value:function(){return this._fieldConfig}},{key:"calculateFieldsConfig",value:function(){return this._fieldConfig=this._fieldspace.fields.reduce(function(e,t,n){return e[t.name()]={index:n,def:t.schema()},e},{}),this}},{key:"dispose",value:function(){this._parent&&this._parent.removeChild(this),this._parent=null,this._children.forEach(function(e){e._parent=null}),this._children=[]}},{key:"removeChild",value:function(e){var t=this._children.findIndex(function(t){return t===e});-1===t||this._children.splice(t,1)}},{key:"setParent",value:function(e){this._parent&&this._parent.removeChild(this),this._parent=e,e&&e._children.push(this)}},{key:"getParent",value:function(){return this._parent}},{key:"getChildren",value:function(){return this._children}},{key:"getDerivations",value:function(){return this._derivation}},{key:"getAncestorDerivations",value:function(){return this._ancestorDerivation}}]),e}(),Yt=function(){return function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],r=!0,a=!1,i=void 0;try{for(var o,u=e[Symbol.iterator]();!(r=(o=u.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(e){a=!0,i=e}finally{try{!r&&u.return&&u.return()}finally{if(a)throw i}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),Bt=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{saveChild:!0},r=""+e.join(),a=[this,e,t],i=ge.apply(void 0,a);return wt(this,i,U.GROUPBY,{fieldsArr:e,groupByString:r,defaultReducer:me.defaultReducer()},t),n.saveChild?i.setParent(this):i.setParent(null),i}},{key:"sort",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{saveChild:!1},n=this.getData({order:"row",sort:e}),r=[n.schema.map(function(e){return e.name})].concat(n.data),a=new this.constructor(r,n.schema,{dataFormat:"DSVArr"});return wt(this,a,U.SORT,t,e),t.saveChild?a.setParent(this):a.setParent(null),a}},{key:"serialize",value:function(e,t){e=e||this._dataFormat,t=Object.assign({},{fieldSeparator:","},t);var n=this.getFieldspace().fields,r=n.map(function(e){return e.formattedData()}),a=r[0].length,i=void 0,u=void 0,c=void 0;if(e===o.FLAT_JSON)for(i=[],u=0;u=0&&(n.fields[a]=e)}else n.fields.push(e),r.forEach(function(t,n){t[e.name()]=new k(e.partialField.data[n],e)});return n._cachedFieldsObj=null,n._cachedDimension=null,n._cachedMeasure=null,this.__calculateFieldspace().calculateFieldsConfig(),this}},{key:"calculateVariable",value:function(e,t,n){var r=this;e=kt(e),n=Object.assign({},{saveChild:!0,replaceVar:!1},n);var a=this.getFieldsConfig(),i=t.slice(0,t.length-1),o=t[t.length-1];if(a[e.name]&&!n.replaceVar)throw new Error(e.name+" field already exists in datamodel");var u=i.map(function(e){var t=a[e];if(!t)throw new Error(e+" is not a valid column name.");return t.index}),c=this.clone(n.saveChild),f=c.getFieldspace().fields,l=u.map(function(e){return f[e]}),s={},d=function(){return r.detachedRoot()},p=[];T(c._rowDiffset,function(e){var t=l.map(function(t){return t.partialField.data[e]});p[e]=o.apply(void 0,Ht(t).concat([e,d,s]))});var h=Xe([p],[e],[e.name]),v=Yt(h,1)[0];return c.addField(v),wt(this,c,U.CAL_VAR,{config:e,fields:i},o),c}},{key:"propagate",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2],r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},a=t.isMutableAction,i=t.sourceId,o=t.payload,u=function(e){for(;e._parent;)e=e._parent;return e}(this),c=u._propagationNameSpace,f={groupByModel:function(e){for(;e._parent&&e._derivation.find(function(e){return e.op!==U.GROUPBY});)e=e._parent;return e}(this),model:u};return n&&function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2],r=void 0,a=t.isMutableAction,i=t.criteria,o=t.action+"-"+t.sourceId;r=a?e.mutableActions:e.immutableActions,null===i?delete r[o]:r[o]={model:n,config:t}}(c,t,this),xt(e,f,{propagationNameSpace:c,sourceId:i},Object.assign({payload:o},t)),a&&function(e,t,n){var r=e.immutableActions;for(var a in r){var i=r[a].config,o=n.config.sourceId,u=!n.propConfig.filterImmutableAction||n.propConfig.filterImmutableAction(i,n.config);if(i.sourceId!==o&&u){var c=i.criteria;xt(c,t,{propagationNameSpace:e,propagateToSource:!1,sourceId:o},i)}}}(c,f,{config:t,propConfig:r}),this}},{key:"on",value:function(e,t){switch(e){case"propagation":this._onPropagation.push(t)}return this}},{key:"unsubscribe",value:function(e){switch(e){case"propagation":this._onPropagation=[]}return this}},{key:"handlePropagation",value:function(e,t){var n=this;this._onPropagation.forEach(function(r){return r.call(n,e,t)})}},{key:"bin",value:function(e,t){var n=this.getFieldsConfig();if(!n[e])throw new Error("Field "+e+" doesn't exist");var r=t.name||e+"_binned";if(n[r])throw new Error("Field "+r+" already exists");var a=function(e,t,n){var r=n.buckets,a=n.binsCount,i=n.binSize,o=n.start,u=n.end,c=e.domain(),f=P(c,2),l=f[0],s=f[1];r||(o=0!==o&&(!o||o>l)?l:o,u=0!==u&&(!u||ul&&r.unshift(l),r[r.length-1]<=s&&r.push(s+1);for(var d=[],p=0;p0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments[2],r={mode:l.NORMAL,saveChild:!0},a=this.getFieldsConfig(),i=Object.keys(a),o=[[t]];return n=Object.assign({},r,n),(e=e.length?e:[[]]).forEach(function(e,n){o[n]=Ut([].concat(Ht(e),Ht(t)),i,a)}),function(e,t,n,r){return t.map(function(t){return Nt(e,t,n,r)})}(this,o,n,i)}}],[{key:"configureInvalidAwareTypes",value:function(e){return M.invalidAwareVals(e)}},{key:"Reducers",get:function(){return me}}]),t}(),Jt=de.sum,zt=de.avg,Kt=de.min,Wt=de.max,Xt=de.first,qt=de.last,Zt=de.count,$t=de.std,Qt={compose:function(){for(var e=arguments.length,t=Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:{saveChild:!0},r=e,a=void 0,i=[];return t.forEach(function(e){r=e(r),i.push.apply(i,function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ta.getFullYear()&&(t=""+(i-1)+r),d(t).getFullYear()},formatter:function(e){var t=d(e).getFullYear().toString(),n=void 0;return t&&(n=t.length,t=t.substring(n-2,n)),t}},Y:{name:"Y",index:0,extract:function(){return"(\\d{4})"},parser:h.defaultNumberParser(),formatter:function(e){return d(e).getFullYear().toString()}}}},h.getTokenFormalNames=function(){var e=h.getTokenDefinitions();return{HOUR:e.H,HOUR_12:e.l,AMPM_UPPERCASE:e.p,AMPM_LOWERCASE:e.P,MINUTE:e.M,SECOND:e.S,SHORT_DAY:e.a,LONG_DAY:e.A,DAY_OF_MONTH:e.e,DAY_OF_MONTH_CONSTANT_WIDTH:e.d,SHORT_MONTH:e.b,LONG_MONTH:e.B,MONTH_OF_YEAR:e.m,SHORT_YEAR:e.y,LONG_YEAR:e.Y}},h.tokenResolver=function(){var e=h.getTokenDefinitions(),t=function(){for(var e=0,t=void 0,n=void 0,r=arguments.length;e=0;)o=e[i+1],-1!==r.indexOf(o)&&a.push({index:i,token:o});return a},h.formatAs=function(e,t){var n,r=d(e),a=h.findTokens(t),i=h.getTokenDefinitions(),o=String(t),u=h.TOKEN_PREFIX,c=void 0,f=void 0,l=void 0;for(l=0,n=a.length;l=0;d--)(f=i[d].index)+1!==s.length-1?(void 0===u&&(u=s.length),l=s.substring(f+2,u),s=s.substring(0,f+2)+RegExp.escape(l)+s.substring(u,s.length),u=f):u=f;for(d=0;d0&&e.split(",").forEach((function(e){var n=e.split("-"),r=+n[0],a=+(n[1]||n[0]);if(a>=r)for(var i=r;i<=a;i+=1)t(i)}))}var R=function(){function e(e,t){for(var n=0;n=(i=e[a=n+Math.floor((r-n)/2)]).start&&t=i.end?n=a+1:t3&&void 0!==arguments[3]&&arguments[3],a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:U.CROSS,i=[],o=[],u=n||H,c=e.getFieldspace(),f=t.getFieldspace(),l=c.name,s=f.name,d=c.name+"."+f.name,p=Y(c,f);if(l===s)throw new Error("DataModels must have different alias names");return c.fields.forEach((function(e){var t=_({},e.schema());-1===p.indexOf(t.name)||r||(t.name=c.name+"."+t.name),i.push(t)})),f.fields.forEach((function(e){var t=_({},e.schema());-1!==p.indexOf(t.name)?r||(t.name=f.name+"."+t.name,i.push(t)):i.push(t)})),T(e._rowDiffset,(function(n){var d=!1,h=void 0;T(t._rowDiffset,(function(v){var m=[],y={};y[l]={},y[s]={},c.fields.forEach((function(e){m.push(e.partialField.data[n]),y[l][e.name()]={rawValue:e.partialField.data[n],formattedValue:e.formattedData()[n]}})),f.fields.forEach((function(e){-1!==p.indexOf(e.schema().name)&&r||m.push(e.partialField.data[v]),y[s][e.name()]={rawValue:e.partialField.data[v],formattedValue:e.formattedData()[v]}}));var g=At(y[l]),b=At(y[s]);if(u(g,b,(function(){return e.detachedRoot()}),(function(){return t.detachedRoot()}),{})){var w={};m.forEach((function(e,t){w[i[t].name]=e})),d&&U.CROSS!==a?o[h]=w:(o.push(w),d=!0,h=n)}else if((a===U.LEFTOUTER||a===U.RIGHTOUTER)&&!d){var O={},_=c.fields.length-1;m.forEach((function(e,t){O[i[t].name]=t<=_?e:null})),d=!0,h=n,o.push(O)}}))})),new on(o,i,{name:d})}function J(e,t){var n=""+e,r=""+t;return nr?1:0}function z(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:J;return e.length>1&&function e(t,n,r,a){if(r===n)return t;var i=n+Math.floor((r-n)/2);return e(t,n,i,a),e(t,i+1,r,a),function(e,t,n,r,a){for(var i=e,o=[],u=t;u<=r;u+=1)o[u]=i[u];for(var c=t,f=n+1,l=t;l<=r;l+=1)c>n?(i[l]=o[f],f+=1):f>r?(i[l]=o[c],c+=1):a(o[c],o[f])<=0?(i[l]=o[c],c+=1):(i[l]=o[f],f+=1)}(t,n,i,r,a),t}(e,0,e.length-1,t),e}var K=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],r=!0,a=!1,i=void 0;try{for(var o,u=e[Symbol.iterator]();!(r=(o=u.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(e){a=!0,i=e}finally{try{!r&&u.return&&u.return()}finally{if(a)throw i}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")};function W(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);tt?1:-1}:function(e,t){return(e=""+e)===(t=""+t)?0:e>t?-1:1}}return n}(e.type,n)}function q(e,t){var n=new Map,r=[];return e.forEach((function(e){var a=e[t];n.has(a)?r[n.get(a)][1].push(e):(r.push([a,[e]]),n.set(a,r.length-1))})),r}function Z(e,t,n){var r={label:e[0]};return t.reduce((function(t,r,a){return t[r]=e[1].map((function(e){return e[n[a].index]})),t}),r),r}function $(e,t,n){for(var r=void 0,a=void 0,i=void 0,o=n.length-1;o>=0;o--)r=n[o][0],a=n[o][1],(i=Ht(t,r))&&("function"==typeof a?z(e,(function(e,t){return a(e[i.index],t[i.index])})):E(a)?function(){var n=q(e,i.index),r=a[a.length-1],o=a.slice(0,a.length-1),u=o.map((function(e){return Ht(t,e)}));n.forEach((function(e){e.push(Z(e,o,u))})),z(n,(function(e,t){var n=e[2],a=t[2];return r(n,a)})),e.length=0,n.forEach((function(t){e.push.apply(e,W(t[1]))}))}():function(){var t=X(i,a);z(e,(function(e,n){return t(e[i.index],n[i.index])}))}())}var Q,ee=function e(t,n,r,a){if(0===t.length)return n;var i=t[0],o=new Map;n.reduce((function(e,t){var n=t[i.index];return e.has(n)?e.get(n).push(t):e.set(n,[t]),e}),o);var u=!0,c=!1,f=void 0;try{for(var l,s=o[Symbol.iterator]();!(u=(l=s.next()).done);u=!0){var d=l.value,p=K(d,2),h=p[0],v=p[1],m=e(t.slice(1),v,r,a);o.set(h,m),Array.isArray(m)&&$(m,r,a)}}catch(e){c=!0,f=e}finally{try{!u&&s.return&&s.return()}finally{if(c)throw f}}return o};function te(e,t){var n=e.schema,r=e.data;if(0!==(t=t.filter((function(e){return!!Ht(n,e[0])}))).length){var a=t.findIndex((function(e){return null===e[1]}));a=-1!==a?a:t.length;var i=t.slice(0,a),o=t.slice(a);$(r,n,i),r=function(e,t,n,r){if(0===(n=n.filter((function(e){return null!==e[1]||(r.push(e[0]),!1)}))).length)return e;r=r.map((function(e){return Ht(t,e)}));var a=ee(r,e,t,n);return e.map((function(e){for(var t=0,n=a;!Array.isArray(n);)n=n.get(e[r[t++].index]);return n.shift()}))}(r,n,o,i.map((function(e){return e[0]}))),e.uids=r.map((function(e){return e.pop()})),e.data=r}}function ne(e,t,n,r,a){a=Object.assign({},{addUid:!1,columnWise:!1},a);var i={schema:[],data:[],uids:[]},o=a.addUid,u=r&&r.length>0,c=[];if(n.split(",").forEach((function(t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},n={},r=e.getFieldspace().getMeasure(),a=_e.defaultReducer();return Object.keys(r).forEach((function(e){"string"!=typeof t[e]&&(t[e]=r[e].defAggFn());var i=_e.resolve(t[e]);i?n[e]=i:(n[e]=a,t[e]=ge)})),n}(e,n),o=e.getFieldspace(),u=o.fieldsObj(),c=o.name,l=[],s=[],d=[],p={},h=[],v=void 0;Object.entries(u).forEach((function(e){var t=Ee(e,2),n=t[0],r=t[1];if(-1!==a.indexOf(n)||i[n])switch(d.push(_({},r.schema())),r.schema().type){case f.MEASURE:s.push(n);break;default:case f.DIMENSION:l.push(n)}}));var m=0;T(e._rowDiffset,(function(e){var t="";l.forEach((function(n){t=t+"-"+u[n].partialField.data[e]})),void 0===p[t]?(p[t]=m,h.push({}),l.forEach((function(t){h[m][t]=u[t].partialField.data[e]})),s.forEach((function(t){h[m][t]=[u[t].partialField.data[e]]})),m+=1):s.forEach((function(n){h[p[t]][n].push(u[n].partialField.data[e])}))}));var y={},g=function(){return e.detachedRoot()};return h.forEach((function(e){var t=e;s.forEach((function(n){t[n]=i[n](e[n],g,y)}))})),r?(r.__calculateFieldspace(),v=r):v=new yn(h,d,{name:c}),v}function je(e,t){var n=Y(e.getFieldspace(),t.getFieldspace());return function(e,t){var r=!0;return n.forEach((function(n){r=!(e[n].internalValue!==t[n].internalValue||!r)})),r}}function Se(e,t){var n={},r=[],a=[],i=[],o=e.getFieldspace(),u=t.getFieldspace(),c=o.fieldsObj(),f=u.fieldsObj(),l=o.name+" union "+u.name;if(!j(e._colIdentifier.split(",").sort(),t._colIdentifier.split(",").sort()))return null;function s(e,t){T(e._rowDiffset,(function(e){var r={},o="";a.forEach((function(n){var a=t[n].partialField.data[e];o+="-"+a,r[n]=a})),n[o]||(i.push(r),n[o]=!0)}))}return e._colIdentifier.split(",").forEach((function(e){var t=c[e];r.push(_({},t.schema())),a.push(t.schema().name)})),s(e,c),s(t,f),new yn(i,r,{name:l})}function De(e,t,n){return G(e,t,n,!1,U.LEFTOUTER)}function Fe(e,t,n){return G(t,e,n,!1,U.RIGHTOUTER)}var Ne=function(){function e(e,t){for(var n=0;nn&&(n=a))})),[t,n]}}]),t}(Ve),He=function(){function e(e,t){for(var n=0;n9999?"+"+st(t,6):st(t,4))+"-"+st(e.getUTCMonth()+1,2)+"-"+st(e.getUTCDate(),2)+(i?"T"+st(n,2)+":"+st(r,2)+":"+st(a,2)+"."+st(i,3)+"Z":a?"T"+st(n,2)+":"+st(r,2)+":"+st(a,2)+"Z":r||n?"T"+st(n,2)+":"+st(r,2)+"Z":"")}var pt=function(e){var t=new RegExp('["'+e+"\n\r]"),n=e.charCodeAt(0);function r(e,t){var r,a=[],i=e.length,o=0,u=0,c=i<=0,f=!1;function l(){if(c)return it;if(f)return f=!1,at;var t,r,a=o;if(e.charCodeAt(a)===ot){for(;o++=i?c=!0:(r=e.charCodeAt(o++))===ut?f=!0:r===ct&&(f=!0,e.charCodeAt(o)===ut&&++o),e.slice(a+1,t-1).replace(/""/g,'"')}for(;o2&&void 0!==arguments[2]?arguments[2]:{},a=arguments[3];t===L.COMPOSE?(e._derivation.length=0,(n=e._derivation).push.apply(n,_t(a))):e._derivation.push({op:t,meta:r,criteria:a})},Dt=function(e,t){var n;(n=t._ancestorDerivation).push.apply(n,_t(e._ancestorDerivation).concat(_t(e._derivation)))},Ft=function(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},a=arguments[4];St(t,n,r,a),Dt(e,t)},Nt=(Ot(gt={},l.NORMAL,{diffIndex:["rowDiffset"],calcDiff:[!0,!1]}),Ot(gt,l.INVERSE,{diffIndex:["rejectRowDiffset"],calcDiff:[!1,!0]}),Ot(gt,l.ALL,{diffIndex:["rowDiffset","rejectRowDiffset"],calcDiff:[!0,!0]}),gt),kt=function(e,t,n){if(-1!==n&&t===n+1){var r=e.length-1;e[r]=e[r].split("-")[0]+"-"+t}else e.push(""+t)},Tt=function(e,t,n){var r=[],a=[],i=wt(Nt[n].calcDiff,2),o=i[0],u=i[1];return T(e,(function(e){var n=t(e);n&&o&&kt(r,e,-1),!n&&u&&kt(a,e,-1)})),{rowDiffset:r.join(","),rejectRowDiffset:a.join(",")}},Rt=function(e,t,n,r,a){var i={},o={},u={};return T(e,(function(e){if(t(e)){var n="",c={keys:{}};r.forEach((function(t){var r=a[t].partialField.data[e];n=n+"-"+r,c.keys[t]=r})),void 0===o[n]&&(o[n]=[],i[n]=-1,u[n]=c),kt(o[n],e,i[n]),i[n]=e}})),{splitRowDiffset:o,dimensionMap:u}},Ct=function(e,t,n,r,a){var i={},o=function(){return r.detachedRoot()},u=n.mode,c=e._rowDiffset,f=e.getPartialFieldspace().fields,l=f.map((function(e){return e.formattedData()})),s=f.map((function(e){return e.data()}));return a(c,(function(e){return t(Et(f,l,s,e),e,o,i)}),u)},Mt=function(e){var t=e.clone(!1),n=e.getPartialFieldspace();return t._colIdentifier=n.fields.map((function(e){return e.name()})).join(","),n._cachedFieldsObj=null,n._cachedDimension=null,n._cachedMeasure=null,t.__calculateFieldspace().calculateFieldsConfig(),t},It=function(e,t,n){for(var r=n(e,t,0),a=1,i=e.length;a2&&void 0!==arguments[2]?arguments[2]:{},r=[],a=n.operation||V,i=n.filterByMeasure||!1,o=Mt(e),u=o.getFieldsConfig();r=t.length?t.map((function(e){return n=void 0,r=(t=e).getData(),a=t.getFieldsConfig(),o=Object.keys(t.getFieldspace().getDimension()).filter((function(e){return e in u})),c=o.length,f=o.map((function(e){return a[e].index})),l=Object.keys(t.getFieldspace().getMeasure()).filter((function(e){return e in u})),s=t.getFieldspace().fieldsObj(),d=r.data,p=l.reduce((function(e,t){return e[t]=s[t].domain(),e}),{}),h={},n=function(e,t,n){return t[e[n]]},c&&d.forEach((function(e){var t=It(f,e,n);h[t]=1})),n=function(e,t,n){return t[e[n]].internalValue},d.length?function(e){var t=!c||h[It(o,e,n)];return i?l.every((function(t){return e[t].internalValue>=p[t][0]&&e[t].internalValue<=p[t][1]}))&&t:t}:function(){return!1};var t,n,r,a,o,c,f,l,s,d,p,h})):[function(){return!1}];return a===V?o.select((function(e){return r.every((function(t){return t(e)}))}),{saveChild:!1}):o.select((function(e){return r.some((function(t){return t(e)}))}),{saveChild:!1})},xt=function(e,t,n,r,a){e._rowDiffset=t,e.__calculateFieldspace().calculateFieldsConfig(),Ft(n,e,L.SELECT,{config:r},a)},Lt=function(e,t,n,r){var a=e.clone(n.saveChild),i=t;return n.mode===l.INVERSE&&(i=r.filter((function(e){return-1===t.indexOf(e)}))),a._colIdentifier=i.join(","),a.__calculateFieldspace().calculateFieldsConfig(),Ft(e,a,L.PROJECT,{projField:t,config:n,actualProjField:i},null),a},Ut=function(e,t,n,r){return t.map((function(t){return Lt(e,t,n,r)}))},Vt=function(e){if((e=_({},e)).type||(e.type=f.DIMENSION),!e.subtype)switch(e.type){case f.MEASURE:e.subtype=c.CONTINUOUS;break;default:case f.DIMENSION:e.subtype=u.CATEGORICAL}return e},Bt=function(e){return e.map((function(e){return function(e){var t=[c.CONTINUOUS],n=[u.CATEGORICAL,u.BINNED,u.TEMPORAL,u.GEO],r=e.type,a=e.subtype,i=e.name;switch(r){case f.DIMENSION:if(-1===n.indexOf(a))throw new Error("DataModel doesn't support dimension field subtype "+a+" used for "+i+" field");break;case f.MEASURE:if(-1===t.indexOf(a))throw new Error("DataModel doesn't support measure field subtype "+a+" used for "+i+" field");break;default:throw new Error("DataModel doesn't support field type "+r+" used for "+i+" field")}}(e=Vt(e)),e}))},Yt=function(e,t,n,r){n=Bt(n),r=Object.assign(Object.assign({},nt),r);var i=a[r.dataFormat];if(!i||"function"!=typeof i)throw new Error("No converter function found for "+r.dataFormat+" format");var u=i(t,n,r),c=wt(u,2),f=c[0],l=c[1];!function(e,t){e.forEach((function(e){var n=e.as;if(n){var r=t.indexOf(e.name);t[r]=n,e.name=n,delete e.as}}))}(n,f);var s=tt(l,n,f),d=F.createNamespace(s,r.name);e._partialFieldspace=d,e._rowDiffset=l.length&&l[0].length?"0-"+(l[0].length-1):"";var p=[],h=d.fields,v=h.map((function(e){return e.data()})),m=h.map((function(e){return e.formattedData()}));return T(e._rowDiffset,(function(e){p[e]=Et(h,m,v,e)})),d._cachedValueObjects=p,e._colIdentifier=n.map((function(e){return e.name})).join(),e._dataFormat=r.dataFormat===o.AUTO?D(t):r.dataFormat,e},Ht=function(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:{},a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},i=a.nonTraversingModel,o=a.excludeModels||[];if(t!==i){var u=!o.length||-1===o.indexOf(t);u&&t.handlePropagation(n,r);var c=t._children;c.forEach((function(t){var i=Gt(n,t);e(t,i,r,a)}))}},zt=function(e){for(;e._parent&&e._derivation.find((function(e){return e.op!==L.GROUPBY}));)e=e._parent;return e},Kt=function(e){for(;e._parent;)e=e._parent;return e},Wt=function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];e._parent;)t.push(e),e=e._parent;return t},Xt=function(e,t,n,r){var a=void 0,i=void 0,o=n.propagationNameSpace,u=n.propagateToSource,c=n.sourceId,f=r.propagateInterpolatedValues,l=[];if(null===e&&!0!==r.persistent)l=[{criteria:[]}],a=[];else{var s,d=Object.values(o.mutableActions);!1!==u&&(d=d.filter((function(e){return e.config.sourceId!==c})));var p=d.filter((function(e){return(r.filterFn||function(){return!0})(e,r)})).map((function(e){return e.config.criteria})),h=[];if(!1!==u){var v=Object.values(o.mutableActions);v.forEach((function(e){var t=e.config;!1===t.applyOnSource&&t.action===r.action&&t.sourceId!==c&&(h.push(e.model),(a=v.filter((function(t){return t!==e})).map((function(e){return e.config.criteria}))).length&&l.push({criteria:a,models:e.model,path:Wt(e.model)}))}))}a=(s=[]).concat.apply(s,[].concat(_t(p),[e])).filter((function(e){return null!==e})),l.push({criteria:a,excludeModels:[].concat(h,_t(r.excludeModels||[]))})}var m=t.model,y=Object.assign({sourceIdentifiers:e,propagationSourceId:c},r),g=t.groupByModel;f&&g&&(i=Pt(g,a,{filterByMeasure:f}),Jt(g,i,y)),l.forEach((function(e){var t=Pt(m,e.criteria),n=e.path;if(n){var r=function(e,t){for(var n=0,r=t.length;n1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2],r=void 0,a=t.isMutableAction,i=t.criteria,o=t.action+"-"+t.sourceId;r=a?e.mutableActions:e.immutableActions,null===i?delete r[o]:r[o]={model:n,config:t}},$t=function(e,t,n){var r=e.reduce((function(e,r){return"RegExp"===r.constructor.name?e.push.apply(e,_t(t.filter((function(e){return-1!==e.search(r)})))):r in n&&e.push(r),e}),[]);return Array.from(new Set(r)).map((function(e){return e.trim()}))},Qt=function(e,t){return e.numberFormat?e.numberFormat()(t):t},en=function(){function e(e,t){for(var n=0;n1?(a=e.clone(r.saveChild),xt(a,u[c[1]],e,n,t),[o,a]):o}(this,e,t,{saveChild:t.saveChild})}},{key:"isEmpty",value:function(){return!this._rowDiffset.length||!this._colIdentifier.length}},{key:"clone",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=new this.constructor(this);return e?t.setParent(this):t.setParent(null),t}},{key:"project",value:function(e,t){var n={mode:l.NORMAL,saveChild:!0};t=Object.assign({},n,t);var r=this.getFieldsConfig(),a=Object.keys(r),i=t.mode,o=$t(e,a,r),u=void 0;i===l.ALL?u=[Lt(this,o,{mode:l.NORMAL,saveChild:t.saveChild},a),Lt(this,o,{mode:l.INVERSE,saveChild:t.saveChild},a)]:u=Lt(this,o,t,a);return u}},{key:"getFieldsConfig",value:function(){return this._fieldConfig}},{key:"calculateFieldsConfig",value:function(){return this._fieldConfig=this._fieldspace.fields.reduce((function(e,t,n){return e[t.name()]={index:n,def:t.schema()},e}),{}),this}},{key:"dispose",value:function(){this._parent&&this._parent.removeChild(this),this._parent=null,this._children.forEach((function(e){e._parent=null})),this._children=[]}},{key:"removeChild",value:function(e){var t=this._children.findIndex((function(t){return t===e}));-1===t||this._children.splice(t,1)}},{key:"setParent",value:function(e){this._parent&&this._parent.removeChild(this),this._parent=e,e&&e._children.push(this)}},{key:"getParent",value:function(){return this._parent}},{key:"getChildren",value:function(){return this._children}},{key:"getDerivations",value:function(){return this._derivation}},{key:"getAncestorDerivations",value:function(){return this._ancestorDerivation}}]),e}(),nn=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],r=!0,a=!1,i=void 0;try{for(var o,u=e[Symbol.iterator]();!(r=(o=u.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(e){a=!0,i=e}finally{try{!r&&u.return&&u.return()}finally{if(a)throw i}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")},rn=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{saveChild:!0},r=""+e.join(),a=[this,e,t],i=Ae.apply(void 0,a);return Ft(this,i,L.GROUPBY,{fieldsArr:e,groupByString:r,defaultReducer:_e.defaultReducer()},t),n.saveChild?i.setParent(this):i.setParent(null),i}},{key:"sort",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{saveChild:!1},n=this.getData({order:"row",sort:e}),r=n.schema.map((function(e){return e.name})),a=[r].concat(n.data),i=new this.constructor(a,n.schema,{dataFormat:"DSVArr"});return Ft(this,i,L.SORT,t,e),t.saveChild?i.setParent(this):i.setParent(null),i}},{key:"serialize",value:function(e,t){e=e||this._dataFormat,t=Object.assign({},{fieldSeparator:","},t);var n=this.getFieldspace().fields,r=n.map((function(e){return e.formattedData()})),a=r[0].length,i=void 0,u=void 0,c=void 0;if(e===o.FLAT_JSON)for(i=[],u=0;u=0&&(n.fields[o]=e)}else n.fields.push(e),r.forEach((function(t,n){t[e.name()]=new k(a[n],i[n],e)}));return n._cachedFieldsObj=null,n._cachedDimension=null,n._cachedMeasure=null,this.__calculateFieldspace().calculateFieldsConfig(),this}},{key:"calculateVariable",value:function(e,t,n){var r=this;e=Vt(e),n=Object.assign({},{saveChild:!0,replaceVar:!1},n);var a=this.getFieldsConfig(),i=t.slice(0,t.length-1),o=t[t.length-1];if(a[e.name]&&!n.replaceVar)throw new Error(e.name+" field already exists in datamodel");var u=i.map((function(e){var t=a[e];if(!t)throw new Error(e+" is not a valid column name.");return t.index})),c=this.clone(n.saveChild),f=c.getFieldspace().fields,l=u.map((function(e){return f[e]})),s={},d=function(){return r.detachedRoot()},p=[];T(c._rowDiffset,(function(e){var t=l.map((function(t){return t.partialField.data[e]}));p[e]=o.apply(void 0,an(t).concat([e,d,s]))}));var h=tt([p],[e],[e.name]),v=nn(h,1)[0];return c.addField(v),Ft(this,c,L.CAL_VAR,{config:e,fields:i},o),c}},{key:"propagate",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments[2],r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},a=t.isMutableAction,i=t.sourceId,o=t.payload,u=Kt(this),c=u._propagationNameSpace,f=zt(this),l={groupByModel:f,model:u};return n&&Zt(c,t,this),Xt(e,l,{propagationNameSpace:c,sourceId:i},Object.assign({payload:o},t)),a&&qt(c,l,{config:t,propConfig:r}),this}},{key:"on",value:function(e,t){switch(e){case"propagation":this._onPropagation.push(t)}return this}},{key:"unsubscribe",value:function(e){switch(e){case"propagation":this._onPropagation=[]}return this}},{key:"handlePropagation",value:function(e,t){var n=this;this._onPropagation.forEach((function(r){return r.call(n,e,t)}))}},{key:"bin",value:function(e,t){var n=this.getFieldsConfig();if(!n[e])throw new Error("Field "+e+" doesn't exist");var r=t.name||e+"_binned";if(n[r])throw new Error("Field "+r+" already exists");var a=function(e,t,n){var r=n.buckets,a=n.binsCount,i=n.binSize,o=n.start,u=n.end,c=e.domain(),f=I(c,2),l=f[0],s=f[1];r||(o=0!==o&&(!o||o>l)?l:o,u=0!==u&&(!u||ul&&r.unshift(l),r[r.length-1]<=s&&r.push(s+1);for(var d=[],p=0;p2&&void 0!==arguments[2]?arguments[2]:function(e){return e},r=arguments[3],a=r.saveChild,i=e.getFieldspace().fieldsObj(),o=Ct(e.clone(a),n,r,e,(function(){for(var e=arguments.length,n=Array(e),r=0;r0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments[2],r={mode:l.NORMAL,saveChild:!0},a=this.getFieldsConfig(),i=Object.keys(a),o=[[t]];return n=Object.assign({},r,n),(e=e.length?e:[[]]).forEach((function(e,n){o[n]=$t([].concat(an(e),an(t)),i,a)})),Ut(this,o,n,i)}}],[{key:"configureInvalidAwareTypes",value:function(e){return M.invalidAwareVals(e)}},{key:"Reducers",get:function(){return _e}}]),t}(tn),un=ye.sum,cn=ye.avg,fn=ye.min,ln=ye.max,sn=ye.first,dn=ye.last,pn=ye.count,hn=ye.std,vn={compose:function(){for(var e=arguments.length,t=Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:{saveChild:!0},r=e,a=void 0,i=[];return t.forEach((function(e){r=e(r),i.push.apply(i,B(r._derivation)),a||(a=r)})),a&&a!==r&&a.dispose(),r._ancestorDerivation=[],Ft(e,r,L.COMPOSE,null,i),n.saveChild?r.setParent(e):r.setParent(null),r}},bin:function(){for(var e=arguments.length,t=Array(e),n=0;n {\n let i;\n let l;\n\n if (!val) { return defVal; }\n\n const nVal = val.toLowerCase();\n\n for (i = 0, l = range.length; i < l; i++) {\n if (range[i].toLowerCase() === nVal) {\n return i;\n }\n }\n\n if (i === undefined) {\n return defVal;\n }\n return null;\n };\n};\n\n/*\n * Defines the tokens which are supporter by the dateformatter. Using this definitation a value gets extracted from\n * the user specifed date string. This also formats the value for display purpose from native JS date.\n * The definition of each token contains the following named properties\n * {\n * %token_name% : {\n * name: name of the token, this is used in reverse lookup,\n * extract: a function that returns the regular expression to extract that piece of information. All the\n * regex should be gouped by using ()\n * parser: a function which receives value extracted by the above regex and parse it to get the date params\n * formatter: a formatter function that takes milliseconds or JS Date object and format the param\n * represented by the token only.\n * }\n * }\n *\n * @return {Object} : Definition of the all the supported tokens.\n */\nDateTimeFormatter.getTokenDefinitions = function () {\n const daysDef = {\n short: [\n 'Sun',\n 'Mon',\n 'Tue',\n 'Wed',\n 'Thu',\n 'Fri',\n 'Sat'\n ],\n long: [\n 'Sunday',\n 'Monday',\n 'Tuesday',\n 'Wednesday',\n 'Thursday',\n 'Friday',\n 'Saturday'\n ]\n };\n const monthsDef = {\n short: [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec'\n ],\n long: [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December'\n ]\n };\n\n const definitions = {\n H: {\n // 24 hours format\n name: 'H',\n index: 3,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n\n return d.getHours().toString();\n }\n },\n l: {\n // 12 hours format\n name: 'l',\n index: 3,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const hours = d.getHours() % 12;\n\n return (hours === 0 ? 12 : hours).toString();\n }\n },\n p: {\n // AM or PM\n name: 'p',\n index: 3,\n extract () { return '(AM|PM)'; },\n parser: (val) => {\n if (val) {\n return val.toLowerCase();\n }\n return null;\n },\n formatter: (val) => {\n const d = convertToNativeDate(val);\n const hours = d.getHours();\n\n return (hours < 12 ? 'AM' : 'PM');\n }\n },\n P: {\n // am or pm\n name: 'P',\n index: 3,\n extract () { return '(am|pm)'; },\n parser: (val) => {\n if (val) {\n return val.toLowerCase();\n }\n return null;\n },\n formatter: (val) => {\n const d = convertToNativeDate(val);\n const hours = d.getHours();\n\n return (hours < 12 ? 'am' : 'pm');\n }\n },\n M: {\n // Two digit minutes 00 - 59\n name: 'M',\n index: 4,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const mins = d.getMinutes();\n\n return pad(mins);\n }\n },\n S: {\n // Two digit seconds 00 - 59\n name: 'S',\n index: 5,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const seconds = d.getSeconds();\n\n return pad(seconds);\n }\n },\n K: {\n // Milliseconds\n name: 'K',\n index: 6,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const ms = d.getMilliseconds();\n\n return ms.toString();\n }\n },\n a: {\n // Short name of day, like Mon\n name: 'a',\n index: 2,\n extract () { return `(${daysDef.short.join('|')})`; },\n parser: DateTimeFormatter.defaultRangeParser(daysDef.short),\n formatter (val) {\n const d = convertToNativeDate(val);\n const day = d.getDay();\n\n return (daysDef.short[day]).toString();\n }\n },\n A: {\n // Long name of day, like Monday\n name: 'A',\n index: 2,\n extract () { return `(${daysDef.long.join('|')})`; },\n parser: DateTimeFormatter.defaultRangeParser(daysDef.long),\n formatter (val) {\n const d = convertToNativeDate(val);\n const day = d.getDay();\n\n return (daysDef.long[day]).toString();\n }\n },\n e: {\n // 8 of March, 11 of November\n name: 'e',\n index: 2,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const day = d.getDate();\n\n return day.toString();\n }\n },\n d: {\n // 08 of March, 11 of November\n name: 'd',\n index: 2,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const day = d.getDate();\n\n return pad(day);\n }\n },\n b: {\n // Short month, like Jan\n name: 'b',\n index: 1,\n extract () { return `(${monthsDef.short.join('|')})`; },\n parser: DateTimeFormatter.defaultRangeParser(monthsDef.short),\n formatter (val) {\n const d = convertToNativeDate(val);\n const month = d.getMonth();\n\n return (monthsDef.short[month]).toString();\n }\n },\n B: {\n // Long month, like January\n name: 'B',\n index: 1,\n extract () { return `(${monthsDef.long.join('|')})`; },\n parser: DateTimeFormatter.defaultRangeParser(monthsDef.long),\n formatter (val) {\n const d = convertToNativeDate(val);\n const month = d.getMonth();\n\n return (monthsDef.long[month]).toString();\n }\n },\n m: {\n // Two digit month of year like 01 for January\n name: 'm',\n index: 1,\n extract () { return '(\\\\d+)'; },\n parser (val) { return DateTimeFormatter.defaultNumberParser()(val) - 1; },\n formatter (val) {\n const d = convertToNativeDate(val);\n const month = d.getMonth();\n\n return pad(month + 1);\n }\n },\n y: {\n // Short year like 90 for 1990\n name: 'y',\n index: 0,\n extract () { return '(\\\\d{2})'; },\n parser (val) {\n let result;\n if (val) {\n const l = val.length;\n val = val.substring(l - 2, l);\n }\n let parsedVal = DateTimeFormatter.defaultNumberParser()(val);\n let presentDate = new Date();\n let presentYear = Math.trunc((presentDate.getFullYear()) / 100);\n\n result = `${presentYear}${parsedVal}`;\n\n if (convertToNativeDate(result).getFullYear() > presentDate.getFullYear()) {\n result = `${presentYear - 1}${parsedVal}`;\n }\n return convertToNativeDate(result).getFullYear();\n },\n formatter (val) {\n const d = convertToNativeDate(val);\n let year = d.getFullYear().toString();\n let l;\n\n if (year) {\n l = year.length;\n year = year.substring(l - 2, l);\n }\n\n return year;\n }\n },\n Y: {\n // Long year like 1990\n name: 'Y',\n index: 0,\n extract () { return '(\\\\d{4})'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const year = d.getFullYear().toString();\n\n return year;\n }\n }\n };\n\n return definitions;\n};\n\n/*\n * The tokens which works internally is not user friendly in terms of memorizing the names. This gives a formal\n * definition to the informal notations.\n *\n * @return {Object} : Formal definition of the tokens\n */\nDateTimeFormatter.getTokenFormalNames = function () {\n const definitions = DateTimeFormatter.getTokenDefinitions();\n\n return {\n HOUR: definitions.H,\n HOUR_12: definitions.l,\n AMPM_UPPERCASE: definitions.p,\n AMPM_LOWERCASE: definitions.P,\n MINUTE: definitions.M,\n SECOND: definitions.S,\n SHORT_DAY: definitions.a,\n LONG_DAY: definitions.A,\n DAY_OF_MONTH: definitions.e,\n DAY_OF_MONTH_CONSTANT_WIDTH: definitions.d,\n SHORT_MONTH: definitions.b,\n LONG_MONTH: definitions.B,\n MONTH_OF_YEAR: definitions.m,\n SHORT_YEAR: definitions.y,\n LONG_YEAR: definitions.Y\n };\n};\n\n/*\n * This defines the rules and declares dependencies that resolves a date parameter (year, month etc) from\n * the date time parameter array.\n *\n * @return {Object} : An object that contains dependencies and a resolver function. The dependencies values are fed\n * to the resolver function in that particular sequence only.\n */\nDateTimeFormatter.tokenResolver = function () {\n const definitions = DateTimeFormatter.getTokenDefinitions();\n const defaultResolver = (...args) => { // eslint-disable-line require-jsdoc\n let i = 0;\n let arg;\n let targetParam;\n const l = args.length;\n\n for (; i < l; i++) {\n arg = args[i];\n if (args[i]) {\n targetParam = arg;\n }\n }\n\n if (!targetParam) { return null; }\n\n return targetParam[0].parser(targetParam[1]);\n };\n\n return {\n YEAR: [definitions.y, definitions.Y,\n defaultResolver\n ],\n MONTH: [definitions.b, definitions.B, definitions.m,\n defaultResolver\n ],\n DAY: [definitions.a, definitions.A, definitions.e, definitions.d,\n defaultResolver\n ],\n HOUR: [definitions.H, definitions.l, definitions.p, definitions.P,\n function (hourFormat24, hourFormat12, ampmLower, ampmUpper) {\n let targetParam;\n let amOrpm;\n let isPM;\n let val;\n\n if (hourFormat12 && (amOrpm = (ampmLower || ampmUpper))) {\n if (amOrpm[0].parser(amOrpm[1]) === 'pm') {\n isPM = true;\n }\n\n targetParam = hourFormat12;\n } else if (hourFormat12) {\n targetParam = hourFormat12;\n } else {\n targetParam = hourFormat24;\n }\n\n if (!targetParam) { return null; }\n\n val = targetParam[0].parser(targetParam[1]);\n if (isPM) {\n val += 12;\n }\n return val;\n }\n ],\n MINUTE: [definitions.M,\n defaultResolver\n ],\n SECOND: [definitions.S,\n defaultResolver\n ]\n };\n};\n\n/*\n * Finds token from the format rule specified by a user.\n * @param format {String} : The format of the input date specified by the user\n * @return {Array} : An array of objects which contains the available token and their occurence index in the format\n */\nDateTimeFormatter.findTokens = function (format) {\n const tokenPrefix = DateTimeFormatter.TOKEN_PREFIX;\n const definitions = DateTimeFormatter.getTokenDefinitions();\n const tokenLiterals = Object.keys(definitions);\n const occurrence = [];\n let i;\n let forwardChar;\n\n while ((i = format.indexOf(tokenPrefix, i + 1)) >= 0) {\n forwardChar = format[i + 1];\n if (tokenLiterals.indexOf(forwardChar) === -1) { continue; }\n\n occurrence.push({\n index: i,\n token: forwardChar\n });\n }\n\n return occurrence;\n};\n\n/*\n * Format any JS date to a specified date given by user.\n *\n * @param date {Number | Date} : The date object which is to be formatted\n * @param format {String} : The format using which the date will be formatted for display\n */\nDateTimeFormatter.formatAs = function (date, format) {\n const nDate = convertToNativeDate(date);\n const occurrence = DateTimeFormatter.findTokens(format);\n const definitions = DateTimeFormatter.getTokenDefinitions();\n let formattedStr = String(format);\n const tokenPrefix = DateTimeFormatter.TOKEN_PREFIX;\n let token;\n let formattedVal;\n let i;\n let l;\n\n for (i = 0, l = occurrence.length; i < l; i++) {\n token = occurrence[i].token;\n formattedVal = definitions[token].formatter(nDate);\n formattedStr = formattedStr.replace(new RegExp(tokenPrefix + token, 'g'), formattedVal);\n }\n\n return formattedStr;\n};\n\n/*\n * Parses the user specified date string to extract the date time params.\n *\n * @return {Array} : Value of date time params in an array [year, month, day, hour, minutes, seconds, milli]\n */\nDateTimeFormatter.prototype.parse = function (dateTimeStamp, options) {\n const tokenResolver = DateTimeFormatter.tokenResolver();\n const dtParams = this.extractTokenValue(dateTimeStamp);\n const dtParamSeq = DateTimeFormatter.DATETIME_PARAM_SEQUENCE;\n const noBreak = options && options.noBreak;\n const dtParamArr = [];\n const args = [];\n let resolverKey;\n let resolverParams;\n let resolverFn;\n let val;\n let i;\n let param;\n let resolvedVal;\n let l;\n let result = [];\n\n for (resolverKey in tokenResolver) {\n if (!{}.hasOwnProperty.call(tokenResolver, resolverKey)) { continue; }\n\n args.length = 0;\n resolverParams = tokenResolver[resolverKey];\n resolverFn = resolverParams.splice(resolverParams.length - 1, 1)[0];\n\n for (i = 0, l = resolverParams.length; i < l; i++) {\n param = resolverParams[i];\n val = dtParams[param.name];\n\n if (val === undefined) {\n args.push(null);\n } else {\n args.push([param, val]);\n }\n }\n\n resolvedVal = resolverFn.apply(this, args);\n\n if ((resolvedVal === undefined || resolvedVal === null) && !noBreak) {\n break;\n }\n\n dtParamArr[dtParamSeq[resolverKey]] = resolvedVal;\n }\n\n if (dtParamArr.length && this.checkIfOnlyYear(dtParamArr.length))\n {\n result.unshift(dtParamArr[0], 0, 1); }\n else {\n result.unshift(...dtParamArr);\n }\n\n return result;\n};\n\n/*\n * Extract the value of the token from user specified date time string.\n *\n * @return {Object} : An key value pair which contains the tokens as key and value as pair\n */\nDateTimeFormatter.prototype.extractTokenValue = function (dateTimeStamp) {\n const format = this.format;\n const definitions = DateTimeFormatter.getTokenDefinitions();\n const tokenPrefix = DateTimeFormatter.TOKEN_PREFIX;\n const occurrence = DateTimeFormatter.findTokens(format);\n const tokenObj = {};\n\n let lastOccurrenceIndex;\n let occObj;\n let occIndex;\n let targetText;\n let regexFormat;\n\n let l;\n let i;\n\n regexFormat = String(format);\n\n const tokenArr = occurrence.map(obj => obj.token);\n const occurrenceLength = occurrence.length;\n for (i = occurrenceLength - 1; i >= 0; i--) {\n occIndex = occurrence[i].index;\n\n if (occIndex + 1 === regexFormat.length - 1) {\n lastOccurrenceIndex = occIndex;\n continue;\n }\n\n if (lastOccurrenceIndex === undefined) {\n lastOccurrenceIndex = regexFormat.length;\n }\n\n targetText = regexFormat.substring(occIndex + 2, lastOccurrenceIndex);\n regexFormat = regexFormat.substring(0, occIndex + 2) +\n RegExp.escape(targetText) +\n regexFormat.substring(lastOccurrenceIndex, regexFormat.length);\n\n lastOccurrenceIndex = occIndex;\n }\n\n for (i = 0; i < occurrenceLength; i++) {\n occObj = occurrence[i];\n regexFormat = regexFormat.replace(tokenPrefix + occObj.token, definitions[occObj.token].extract());\n }\n\n const extractValues = dateTimeStamp.match(new RegExp(regexFormat)) || [];\n extractValues.shift();\n\n for (i = 0, l = tokenArr.length; i < l; i++) {\n tokenObj[tokenArr[i]] = extractValues[i];\n }\n return tokenObj;\n};\n\n/*\n * Give back the JS native date formed from user specified date string\n *\n * @return {Date} : Native JS Date\n */\nDateTimeFormatter.prototype.getNativeDate = function (dateTimeStamp) {\n let date = null;\n if (Number.isFinite(dateTimeStamp)) {\n date = new Date(dateTimeStamp);\n } else if (!this.format && Date.parse(dateTimeStamp)) {\n date = new Date(dateTimeStamp);\n }\n else {\n const dtParams = this.dtParams = this.parse(dateTimeStamp);\n if (dtParams.length) {\n this.nativeDate = new Date(...dtParams);\n date = this.nativeDate;\n }\n }\n return date;\n};\n\nDateTimeFormatter.prototype.checkIfOnlyYear = function(len) {\n return len === 1 && this.format.match(/y|Y/g).length;\n};\n\n/*\n * Represents JS native date to a user specified format.\n *\n * @param format {String} : The format according to which the date is to be represented\n * @return {String} : The formatted date string\n */\nDateTimeFormatter.prototype.formatAs = function (format, dateTimeStamp) {\n let nativeDate;\n\n if (dateTimeStamp) {\n nativeDate = this.nativeDate = this.getNativeDate(dateTimeStamp);\n } else if (!(nativeDate = this.nativeDate)) {\n nativeDate = this.getNativeDate(dateTimeStamp);\n }\n\n return DateTimeFormatter.formatAs(nativeDate, format);\n};\n\nexport { DateTimeFormatter as default };\n","/**\n * The utility function to calculate major column.\n *\n * @param {Object} store - The store object.\n * @return {Function} Returns the push function.\n */\nexport default (store) => {\n let i = 0;\n return (...fields) => {\n fields.forEach((val, fieldIndex) => {\n if (!(store[fieldIndex] instanceof Array)) {\n store[fieldIndex] = Array.from({ length: i });\n }\n store[fieldIndex].push(val);\n });\n i++;\n };\n};\n","/* eslint-disable */\nconst OBJECTSTRING = 'object';\nconst objectToStrFn = Object.prototype.toString;\nconst objectToStr = '[object Object]';\nconst arrayToStr = '[object Array]';\n\nfunction checkCyclicRef(obj, parentArr) {\n let i = parentArr.length;\n let bIndex = -1;\n\n while (i) {\n if (obj === parentArr[i]) {\n bIndex = i;\n return bIndex;\n }\n i -= 1;\n }\n\n return bIndex;\n}\n\nfunction merge(obj1, obj2, skipUndef, tgtArr, srcArr) {\n var item,\n srcVal,\n tgtVal,\n str,\n cRef;\n // check whether obj2 is an array\n // if array then iterate through it's index\n // **** MOOTOOLS precution\n\n if (!srcArr) {\n tgtArr = [obj1];\n srcArr = [obj2];\n }\n else {\n tgtArr.push(obj1);\n srcArr.push(obj2);\n }\n\n if (obj2 instanceof Array) {\n for (item = 0; item < obj2.length; item += 1) {\n try {\n srcVal = obj1[item];\n tgtVal = obj2[item];\n }\n catch (e) {\n continue;\n }\n\n if (typeof tgtVal !== OBJECTSTRING) {\n if (!(skipUndef && tgtVal === undefined)) {\n obj1[item] = tgtVal;\n }\n }\n else {\n if (srcVal === null || typeof srcVal !== OBJECTSTRING) {\n srcVal = obj1[item] = tgtVal instanceof Array ? [] : {};\n }\n cRef = checkCyclicRef(tgtVal, srcArr);\n if (cRef !== -1) {\n srcVal = obj1[item] = tgtArr[cRef];\n }\n else {\n merge(srcVal, tgtVal, skipUndef, tgtArr, srcArr);\n }\n }\n }\n }\n else {\n for (item in obj2) {\n try {\n srcVal = obj1[item];\n tgtVal = obj2[item];\n }\n catch (e) {\n continue;\n }\n\n if (tgtVal !== null && typeof tgtVal === OBJECTSTRING) {\n // Fix for issue BUG: FWXT-602\n // IE < 9 Object.prototype.toString.call(null) gives\n // '[object Object]' instead of '[object Null]'\n // that's why null value becomes Object in IE < 9\n str = objectToStrFn.call(tgtVal);\n if (str === objectToStr) {\n if (srcVal === null || typeof srcVal !== OBJECTSTRING) {\n srcVal = obj1[item] = {};\n }\n cRef = checkCyclicRef(tgtVal, srcArr);\n if (cRef !== -1) {\n srcVal = obj1[item] = tgtArr[cRef];\n }\n else {\n merge(srcVal, tgtVal, skipUndef, tgtArr, srcArr);\n }\n }\n else if (str === arrayToStr) {\n if (srcVal === null || !(srcVal instanceof Array)) {\n srcVal = obj1[item] = [];\n }\n cRef = checkCyclicRef(tgtVal, srcArr);\n if (cRef !== -1) {\n srcVal = obj1[item] = tgtArr[cRef];\n }\n else {\n merge(srcVal, tgtVal, skipUndef, tgtArr, srcArr);\n }\n }\n else {\n obj1[item] = tgtVal;\n }\n }\n else {\n if (skipUndef && tgtVal === undefined) {\n continue;\n }\n obj1[item] = tgtVal;\n }\n }\n }\n return obj1;\n}\n\n\nfunction extend2 (obj1, obj2, skipUndef) {\n //if none of the arguments are object then return back\n if (typeof obj1 !== OBJECTSTRING && typeof obj2 !== OBJECTSTRING) {\n return null;\n }\n\n if (typeof obj2 !== OBJECTSTRING || obj2 === null) {\n return obj1;\n }\n\n if (typeof obj1 !== OBJECTSTRING) {\n obj1 = obj2 instanceof Array ? [] : {};\n }\n merge(obj1, obj2, skipUndef);\n return obj1;\n}\n\nexport { extend2 as default };\n","import { DataFormat } from '../enums';\n\n/**\n * Checks whether the value is an array.\n *\n * @param {*} val - The value to be checked.\n * @return {boolean} Returns true if the value is an array otherwise returns false.\n */\nexport function isArray (val) {\n return Array.isArray(val);\n}\n\n/**\n * Checks whether the value is an object.\n *\n * @param {*} val - The value to be checked.\n * @return {boolean} Returns true if the value is an object otherwise returns false.\n */\nexport function isObject (val) {\n return val === Object(val);\n}\n\n/**\n * Checks whether the value is a string value.\n *\n * @param {*} val - The value to be checked.\n * @return {boolean} Returns true if the value is a string value otherwise returns false.\n */\nexport function isString (val) {\n return typeof val === 'string';\n}\n\n/**\n * Checks whether the value is callable.\n *\n * @param {*} val - The value to be checked.\n * @return {boolean} Returns true if the value is callable otherwise returns false.\n */\nexport function isCallable (val) {\n return typeof val === 'function';\n}\n\n/**\n * Returns the unique values from the input array.\n *\n * @param {Array} data - The input array.\n * @return {Array} Returns a new array of unique values.\n */\nexport function uniqueValues (data) {\n return [...new Set(data)];\n}\n\nexport const getUniqueId = () => `id-${new Date().getTime()}${Math.round(Math.random() * 10000)}`;\n\n/**\n * Checks Whether two arrays have same content.\n *\n * @param {Array} arr1 - The first array.\n * @param {Array} arr2 - The 2nd array.\n * @return {boolean} Returns whether two array have same content.\n */\nexport function isArrEqual(arr1, arr2) {\n if (!isArray(arr1) || !isArray(arr2)) {\n return arr1 === arr2;\n }\n\n if (arr1.length !== arr2.length) {\n return false;\n }\n\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * It is the default number format function for the measure field type.\n *\n * @param {any} val - The input value.\n * @return {number} Returns a number value.\n */\nexport function formatNumber(val) {\n return val;\n}\n\n/**\n * Returns the detected data format.\n *\n * @param {any} data - The input data to be tested.\n * @return {string} Returns the data format name.\n */\nexport const detectDataFormat = (data) => {\n if (isString(data)) {\n return DataFormat.DSV_STR;\n } else if (isArray(data) && isArray(data[0])) {\n return DataFormat.DSV_ARR;\n } else if (isArray(data) && (data.length === 0 || isObject(data[0]))) {\n return DataFormat.FLAT_JSON;\n }\n return null;\n};\n","import { FieldType } from './enums';\nimport { getUniqueId } from './utils';\n\nconst fieldStore = {\n data: {},\n\n createNamespace (fieldArr, name) {\n const dataId = name || getUniqueId();\n\n this.data[dataId] = {\n name: dataId,\n fields: fieldArr,\n\n fieldsObj () {\n let fieldsObj = this._cachedFieldsObj;\n\n if (!fieldsObj) {\n fieldsObj = this._cachedFieldsObj = {};\n this.fields.forEach((field) => {\n fieldsObj[field.name()] = field;\n });\n }\n return fieldsObj;\n },\n getMeasure () {\n let measureFields = this._cachedMeasure;\n\n if (!measureFields) {\n measureFields = this._cachedMeasure = {};\n this.fields.forEach((field) => {\n if (field.schema().type === FieldType.MEASURE) {\n measureFields[field.name()] = field;\n }\n });\n }\n return measureFields;\n },\n getDimension () {\n let dimensionFields = this._cachedDimension;\n\n if (!this._cachedDimension) {\n dimensionFields = this._cachedDimension = {};\n this.fields.forEach((field) => {\n if (field.schema().type === FieldType.DIMENSION) {\n dimensionFields[field.name()] = field;\n }\n });\n }\n return dimensionFields;\n },\n };\n return this.data[dataId];\n },\n};\n\nexport default fieldStore;\n","/**\n * The wrapper class on top of the primitive value of a field.\n *\n * @todo Need to have support for StringValue, NumberValue, DateTimeValue\n * and GeoValue. These types should expose predicate API mostly.\n */\nclass Value {\n\n /**\n * Creates new Value instance.\n *\n * @param {*} val - the primitive value from the field cell.\n * @param {string | Field} field - The field from which the value belongs.\n */\n constructor (val, field) {\n Object.defineProperty(this, '_value', {\n enumerable: false,\n configurable: false,\n writable: false,\n value: val\n });\n\n this.field = field;\n }\n\n /**\n * Returns the field value.\n *\n * @return {*} Returns the current value.\n */\n get value () {\n return this._value;\n }\n\n /**\n * Converts to human readable string.\n *\n * @override\n * @return {string} Returns a human readable string of the field value.\n *\n */\n toString () {\n return String(this.value);\n }\n\n /**\n * Returns the value of the field.\n *\n * @override\n * @return {*} Returns the field value.\n */\n valueOf () {\n return this.value;\n }\n}\n\nexport default Value;\n","/**\n * Iterates through the diffSet array and call the callback with the current\n * index.\n *\n * @param {string} rowDiffset - The row diffset string e.g. '0-4,6,10-13'.\n * @param {Function} callback - The callback function to be called with every index.\n */\nexport function rowDiffsetIterator (rowDiffset, callback) {\n if (rowDiffset.length > 0) {\n const rowDiffArr = rowDiffset.split(',');\n rowDiffArr.forEach((diffStr) => {\n const diffStsArr = diffStr.split('-');\n const start = +(diffStsArr[0]);\n const end = +(diffStsArr[1] || diffStsArr[0]);\n if (end >= start) {\n for (let i = start; i <= end; i += 1) {\n callback(i);\n }\n }\n });\n }\n}\n","/**\n * A parser to parser null, undefined, invalid and NIL values.\n *\n * @public\n * @class\n */\nclass InvalidAwareTypes {\n /**\n * Static method which gets/sets the invalid value registry.\n *\n * @public\n * @param {Object} config - The custom configuration supplied by user.\n * @return {Object} Returns the invalid values registry.\n */\n static invalidAwareVals (config) {\n if (!config) {\n return InvalidAwareTypes._invalidAwareValsMap;\n }\n return Object.assign(InvalidAwareTypes._invalidAwareValsMap, config);\n }\n\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {string} value - The value of the invalid data type.\n */\n constructor (value) {\n this._value = value;\n }\n\n /**\n * Returns the current value of the instance.\n *\n * @public\n * @return {string} Returns the value of the invalid data type.\n */\n value () {\n return this._value;\n }\n\n /**\n * Returns the current value of the instance in string format.\n *\n * @public\n * @return {string} Returns the value of the invalid data type.\n */\n toString () {\n return String(this._value);\n }\n\n static isInvalid(val) {\n return (val instanceof InvalidAwareTypes) || !!InvalidAwareTypes.invalidAwareVals()[val];\n }\n\n static getInvalidType(val) {\n return val instanceof InvalidAwareTypes ? val : InvalidAwareTypes.invalidAwareVals()[val];\n }\n}\n\n/**\n * Enums for Invalid types.\n */\nInvalidAwareTypes.NULL = new InvalidAwareTypes('null');\nInvalidAwareTypes.NA = new InvalidAwareTypes('na');\nInvalidAwareTypes.NIL = new InvalidAwareTypes('nil');\n\n/**\n * Default Registry for mapping the invalid values.\n *\n * @private\n */\nInvalidAwareTypes._invalidAwareValsMap = {\n invalid: InvalidAwareTypes.NA,\n nil: InvalidAwareTypes.NIL,\n null: InvalidAwareTypes.NULL,\n undefined: InvalidAwareTypes.NA\n};\n\nexport default InvalidAwareTypes;\n","import { rowDiffsetIterator } from './row-diffset-iterator';\nimport InvalidAwareTypes from '../invalid-aware-types';\n\nconst generateBuckets = (binSize, start, end) => {\n const buckets = [];\n let next = start;\n\n while (next < end) {\n buckets.push(next);\n next += binSize;\n }\n buckets.push(next);\n\n return buckets;\n};\n\nconst findBucketRange = (bucketRanges, value) => {\n let leftIdx = 0;\n let rightIdx = bucketRanges.length - 1;\n let midIdx;\n let range;\n\n // Here use binary search as the bucketRanges is a sorted array\n while (leftIdx <= rightIdx) {\n midIdx = leftIdx + Math.floor((rightIdx - leftIdx) / 2);\n range = bucketRanges[midIdx];\n\n if (value >= range.start && value < range.end) {\n return range;\n } else if (value >= range.end) {\n leftIdx = midIdx + 1;\n } else if (value < range.start) {\n rightIdx = midIdx - 1;\n }\n }\n\n return null;\n};\n\n /**\n * Creates the bin data from input measure field and supplied configs.\n *\n * @param {Measure} measureField - The Measure field instance.\n * @param {string} rowDiffset - The datamodel rowDiffset values.\n * @param {Object} config - The config object.\n * @return {Object} Returns the binned data and the corresponding bins.\n */\nexport function createBinnedFieldData (measureField, rowDiffset, config) {\n let { buckets, binsCount, binSize, start, end } = config;\n const [dMin, dMax] = measureField.domain();\n\n if (!buckets) {\n start = (start !== 0 && (!start || start > dMin)) ? dMin : start;\n end = (end !== 0 && (!end || end < dMax)) ? (dMax + 1) : end;\n\n if (binsCount) {\n binSize = Math.ceil(Math.abs(end - start) / binsCount);\n }\n\n buckets = generateBuckets(binSize, start, end);\n }\n\n if (buckets[0] > dMin) {\n buckets.unshift(dMin);\n }\n if (buckets[buckets.length - 1] <= dMax) {\n buckets.push(dMax + 1);\n }\n\n const bucketRanges = [];\n for (let i = 0; i < buckets.length - 1; i++) {\n bucketRanges.push({\n start: buckets[i],\n end: buckets[i + 1]\n });\n }\n\n const binnedData = [];\n rowDiffsetIterator(rowDiffset, (i) => {\n const datum = measureField.partialField.data[i];\n if (datum instanceof InvalidAwareTypes) {\n binnedData.push(datum);\n return;\n }\n\n const range = findBucketRange(bucketRanges, datum);\n binnedData.push(`${range.start}-${range.end}`);\n });\n\n return { binnedData, bins: buckets };\n}\n","export { DataFormat, FilteringMode } from '../enums';\n/**\n * The event name for data propagation.\n */\nexport const PROPAGATION = 'propagation';\n\n/**\n * The name of the unique row id column in DataModel.\n */\nexport const ROW_ID = '__id__';\n\n/**\n * The enums for operation names performed on DataModel.\n */\nexport const DM_DERIVATIVES = {\n SELECT: 'select',\n PROJECT: 'project',\n GROUPBY: 'group',\n COMPOSE: 'compose',\n CAL_VAR: 'calculatedVariable',\n BIN: 'bin',\n SORT: 'sort'\n};\n\nexport const JOINS = {\n CROSS: 'cross',\n LEFTOUTER: 'leftOuter',\n RIGHTOUTER: 'rightOuter',\n NATURAL: 'natural',\n FULLOUTER: 'fullOuter'\n};\n\nexport const LOGICAL_OPERATORS = {\n AND: 'and',\n OR: 'or'\n};\n","import { persistDerivations } from '../helper';\nimport { DM_DERIVATIVES } from '../constants';\n\n/**\n * DataModel's opearators are exposed as composable functional operators as well as chainable operators. Chainable\n * operators are called on the instances of {@link Datamodel} and {@link Relation} class.\n *\n * Those same operators can be used as composable operators from `DataModel.Operators` namespace.\n *\n * All these operators have similar behaviour. All these operators when called with the argument returns a function\n * which expects a DataModel instance.\n *\n * @public\n * @module Operators\n * @namespace DataModel\n */\n\n/**\n * This is functional version of selection operator. {@link link_to_selection | Selection} is a row filtering operation.\n * It takes {@link SelectionPredicate | predicate} for filtering criteria and returns a function.\n * The returned function is called with the DataModel instance on which the action needs to be performed.\n *\n * {@link SelectionPredicate} is a function which returns a boolean value. For selection opearation the selection\n * function is called for each row of DataModel instance with the current row passed as argument.\n *\n * After executing {@link SelectionPredicate} the rows are labeled as either an entry of selection set or an entry\n * of rejection set.\n *\n * {@link FilteringMode} operates on the selection and rejection set to determine which one would reflect in the\n * resulatant datamodel.\n *\n * @warning\n * [Warn] Selection and rejection set is only a logical idea for concept explanation purpose.\n *\n * @error\n * [Error] `FilteringMode.ALL` is not a valid working mode for functional version of `select`. Its only avialable on the\n * chained version.\n *\n * @example\n * const select = DataModel.Operators.select;\n * usaCarsFn = select(fields => fields.Origin.value === 'USA');\n * usaCarsDm = usaCarsFn(dm);\n * console.log(usaCarsDm);\n *\n * @public\n * @namespace DataModel\n * @module Operators\n *\n * @param {SelectionPredicate} selectFn - Predicate funciton which is called for each row with the current row\n * ```\n * function (row, i) { ... }\n * ```\n * @param {Object} [config] - The configuration object to control the inclusion exclusion of a row in resultant\n * DataModel instance\n * @param {FilteringMode} [config.mode=FilteringMode.NORMAL] - The mode of the selection\n *\n * @return {PreparatorFunction} Function which expects an instance of DataModel on which the operator needs to be\n * applied.\n */\nexport const select = (...args) => dm => dm.select(...args);\n\n/**\n * This is functional version of projection operator. {@link link_to_projection | Projection} is a column filtering\n * operation.It expects list of fields name and either include those or exclude those based on {@link FilteringMode} on\n * the resultant variable.It returns a function which is called with the DataModel instance on which the action needs\n * to be performed.\n *\n * Projection expects array of fields name based on which it creates the selection and rejection set. All the field\n * whose name is present in array goes in selection set and rest of the fields goes in rejection set.\n *\n * {@link FilteringMode} operates on the selection and rejection set to determine which one would reflect in the\n * resulatant datamodel.\n *\n * @warning\n * Selection and rejection set is only a logical idea for concept explanation purpose.\n *\n * @error\n * `FilteringMode.ALL` is not a valid working mode for functional version of `select`. Its only avialable on the\n * chained version.\n *\n * @public\n * @namespace DataModel\n * @module Operators\n *\n * @param {Array.} projField - An array of column names in string or regular expression.\n * @param {Object} [config] - An optional config to control the creation of new DataModel\n * @param {FilteringMode} [config.mode=FilteringMode.NORMAL] - Mode of the projection\n *\n * @return {PreparatorFunction} Function which expects an instance of DataModel on which the operator needs to be\n * applied.\n */\nexport const project = (...args) => dm => dm.project(...args);\n\n/**\n * This is functional version of binnig operator. Binning happens on a measure field based on a binning configuration.\n * Binning in DataModel does not aggregate the number of rows present in DataModel instance after binning, it just adds\n * a new field with the binned value. Refer binning {@link example_of_binning | example} to have a intuition of what\n * binning is and the use case.\n *\n * Binning can be configured by\n * - providing custom bin configuration with non uniform buckets\n * - providing bin count\n * - providing each bin size\n *\n * When custom buckets are provided as part of binning configuration\n * @example\n * // DataModel already prepared and assigned to dm vairable\n * const buckets = {\n * start: 30\n * stops: [80, 100, 110]\n * };\n * const config = { buckets, name: 'binnedHP' }\n * const binFn = bin('horsepower', config);\n * const binnedDm = binFn(dm);\n *\n * @text\n * When `binCount` is defined as part of binning configuration\n * @example\n * // DataModel already prepared and assigned to dm vairable\n * const config = { binCount: 5, name: 'binnedHP' }\n * const binFn = bin('horsepower', config);\n * const binnedDm = binFn(Dm);\n *\n * @text\n * When `binSize` is defined as part of binning configuration\n * @example\n * // DataModel already prepared and assigned to dm vairable\n * const config = { binSize: 200, name: 'binnedHorsepower' }\n * const binnedDm = dataModel.bin('horsepower', config);\n * const binnedDm = binFn(Dm);\n *\n * @public\n * @namespace DataModel\n * @module Operators\n *\n * @param {String} name Name of measure which will be used to create bin\n * @param {Object} config Config required for bin creation\n * @param {Array.} config.bucketObj.stops Defination of bucket ranges. Two subsequent number from arrays\n * are picked and a range is created. The first number from range is inclusive and the second number from range\n * is exclusive.\n * @param {Number} [config.bucketObj.startAt] Force the start of the bin from a particular number.\n * If not mentioned, the start of the bin or the lower domain of the data if stops is not mentioned, else its\n * the first value of the stop.\n * @param {Number} config.binSize Bucket size for each bin\n * @param {Number} config.binCount Number of bins which will be created\n * @param {String} config.name Name of the new binned field to be created\n *\n * @return {PreparatorFunction} Function which expects an instance of DataModel on which the operator needs to be\n * applied.\n */\nexport const bin = (...args) => dm => dm.bin(...args);\n\n/**\n * This is functional version of `groupBy` operator.Groups the data using particular dimensions and by reducing\n * measures. It expects a list of dimensions using which it projects the datamodel and perform aggregations to reduce\n * the duplicate tuples. Refer this {@link link_to_one_example_with_group_by | document} to know the intuition behind\n * groupBy.\n *\n * DataModel by default provides definition of few {@link reducer | Reducers}.\n * {@link ReducerStore | User defined reducers} can also be registered.\n *\n * This is the chained implementation of `groupBy`.\n * `groupBy` also supports {@link link_to_compose_groupBy | composability}\n *\n * @example\n * const groupBy = DataModel.Operators.groupBy;\n * const groupedFn = groupBy(['Year'], { horsepower: 'max' } );\n * groupedDM = groupByFn(dm);\n *\n * @public\n *\n * @param {Array.} fieldsArr - Array containing the name of dimensions\n * @param {Object} [reducers={}] - A map whose key is the variable name and value is the name of the reducer. If its\n * not passed, or any variable is ommitted from the object, default aggregation function is used from the\n * schema of the variable.\n *\n * @return {PreparatorFunction} Function which expects an instance of DataModel on which the operator needs to be\n * applied.\n */\nexport const groupBy = (...args) => dm => dm.groupBy(...args);\n\n/**\n * Enables composing operators to run multiple operations and save group of operataion as named opration on a DataModel.\n * The resulting DataModel will be the result of all the operation provided. The operations provided will be executed in\n * a serial manner ie. result of one operation will be the input for the next operations (like pipe operator in unix).\n *\n * Suported operations in compose are\n * - `select`\n * - `project`\n * - `groupBy`\n * - `bin`\n * - `compose`\n *\n * @example\n * const compose = DataModel.Operators.compose;\n * const select = DataModel.Operators.select;\n * const project = DataModel.Operators.project;\n *\n * let composedFn = compose(\n * select(fields => fields.netprofit.value <= 15),\n * project(['netprofit', 'netsales']));\n *\n * const dataModel = new DataModel(data1, schema1);\n *\n * let composedDm = composedFn(dataModel);\n *\n * @public\n * @namespace DataModel\n * @module Operators\n *\n * @param {Array.} operators: An array of operation that will be applied on the\n * datatable.\n *\n * @returns {DataModel} Instance of resultant DataModel\n */\nexport const compose = (...operations) =>\n (dm, config = { saveChild: true }) => {\n let currentDM = dm;\n let firstChild;\n const derivations = [];\n\n operations.forEach((operation) => {\n currentDM = operation(currentDM);\n derivations.push(...currentDM._derivation);\n if (!firstChild) {\n firstChild = currentDM;\n }\n });\n\n if (firstChild && firstChild !== currentDM) {\n firstChild.dispose();\n }\n\n // reset all ancestorDerivation saved in-between compose\n currentDM._ancestorDerivation = [];\n persistDerivations(\n dm,\n currentDM,\n DM_DERIVATIVES.COMPOSE,\n null,\n derivations\n );\n\n if (config.saveChild) {\n currentDM.setParent(dm);\n } else {\n currentDM.setParent(null);\n }\n\n return currentDM;\n };\n","/**\n * The helper function that returns an array of common schema\n * from two fieldStore instances.\n *\n * @param {FieldStore} fs1 - The first FieldStore instance.\n * @param {FieldStore} fs2 - The second FieldStore instance.\n * @return {Array} An array containing the common schema.\n */\nexport function getCommonSchema (fs1, fs2) {\n const retArr = [];\n const fs1Arr = [];\n fs1.fields.forEach((field) => {\n fs1Arr.push(field.schema().name);\n });\n fs2.fields.forEach((field) => {\n if (fs1Arr.indexOf(field.schema().name) !== -1) {\n retArr.push(field.schema().name);\n }\n });\n return retArr;\n}\n","import DataModel from '../datamodel';\nimport { extend2 } from '../utils';\nimport { getCommonSchema } from './get-common-schema';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport { JOINS } from '../constants';\nimport { prepareJoinData } from '../helper';\n/**\n * Default filter function for crossProduct.\n *\n * @return {boolean} Always returns true.\n */\nfunction defaultFilterFn() { return true; }\n\n/**\n * Implementation of cross product operation between two DataModel instances.\n * It internally creates the data and schema for the new DataModel.\n *\n * @param {DataModel} dataModel1 - The left DataModel instance.\n * @param {DataModel} dataModel2 - The right DataModel instance.\n * @param {Function} filterFn - The filter function which is used to filter the tuples.\n * @param {boolean} [replaceCommonSchema=false] - The flag if the common name schema should be there.\n * @return {DataModel} Returns The newly created DataModel instance from the crossProduct operation.\n */\nexport function crossProduct (dm1, dm2, filterFn, replaceCommonSchema = false, jointype = JOINS.CROSS) {\n const schema = [];\n const data = [];\n const applicableFilterFn = filterFn || defaultFilterFn;\n const dm1FieldStore = dm1.getFieldspace();\n const dm2FieldStore = dm2.getFieldspace();\n const dm1FieldStoreName = dm1FieldStore.name;\n const dm2FieldStoreName = dm2FieldStore.name;\n const name = `${dm1FieldStore.name}.${dm2FieldStore.name}`;\n const commonSchemaList = getCommonSchema(dm1FieldStore, dm2FieldStore);\n\n if (dm1FieldStoreName === dm2FieldStoreName) {\n throw new Error('DataModels must have different alias names');\n }\n // Here prepare the schema\n dm1FieldStore.fields.forEach((field) => {\n const tmpSchema = extend2({}, field.schema());\n if (commonSchemaList.indexOf(tmpSchema.name) !== -1 && !replaceCommonSchema) {\n tmpSchema.name = `${dm1FieldStore.name}.${tmpSchema.name}`;\n }\n schema.push(tmpSchema);\n });\n dm2FieldStore.fields.forEach((field) => {\n const tmpSchema = extend2({}, field.schema());\n if (commonSchemaList.indexOf(tmpSchema.name) !== -1) {\n if (!replaceCommonSchema) {\n tmpSchema.name = `${dm2FieldStore.name}.${tmpSchema.name}`;\n schema.push(tmpSchema);\n }\n } else {\n schema.push(tmpSchema);\n }\n });\n\n // Here prepare Data\n rowDiffsetIterator(dm1._rowDiffset, (i) => {\n let rowAdded = false;\n let rowPosition;\n rowDiffsetIterator(dm2._rowDiffset, (ii) => {\n const tuple = [];\n const userArg = {};\n userArg[dm1FieldStoreName] = {};\n userArg[dm2FieldStoreName] = {};\n dm1FieldStore.fields.forEach((field) => {\n tuple.push(field.partialField.data[i]);\n userArg[dm1FieldStoreName][field.name()] = field.partialField.data[i];\n });\n dm2FieldStore.fields.forEach((field) => {\n if (!(commonSchemaList.indexOf(field.schema().name) !== -1 && replaceCommonSchema)) {\n tuple.push(field.partialField.data[ii]);\n }\n userArg[dm2FieldStoreName][field.name()] = field.partialField.data[ii];\n });\n\n let cachedStore = {};\n let cloneProvider1 = () => dm1.detachedRoot();\n let cloneProvider2 = () => dm2.detachedRoot();\n\n const dm1Fields = prepareJoinData(userArg[dm1FieldStoreName]);\n const dm2Fields = prepareJoinData(userArg[dm2FieldStoreName]);\n if (applicableFilterFn(dm1Fields, dm2Fields, cloneProvider1, cloneProvider2, cachedStore)) {\n const tupleObj = {};\n tuple.forEach((cellVal, iii) => {\n tupleObj[schema[iii].name] = cellVal;\n });\n if (rowAdded && JOINS.CROSS !== jointype) {\n data[rowPosition] = tupleObj;\n }\n else {\n data.push(tupleObj);\n rowAdded = true;\n rowPosition = i;\n }\n } else if ((jointype === JOINS.LEFTOUTER || jointype === JOINS.RIGHTOUTER) && !rowAdded) {\n const tupleObj = {};\n let len = dm1FieldStore.fields.length - 1;\n tuple.forEach((cellVal, iii) => {\n if (iii <= len) {\n tupleObj[schema[iii].name] = cellVal;\n }\n else {\n tupleObj[schema[iii].name] = null;\n }\n });\n rowAdded = true;\n rowPosition = i;\n data.push(tupleObj);\n }\n });\n });\n\n return new DataModel(data, schema, { name });\n}\n","/**\n * The default sort function.\n *\n * @param {*} a - The first value.\n * @param {*} b - The second value.\n * @return {number} Returns the comparison result e.g. 1 or 0 or -1.\n */\nfunction defSortFn (a, b) {\n const a1 = `${a}`;\n const b1 = `${b}`;\n if (a1 < b1) {\n return -1;\n }\n if (a1 > b1) {\n return 1;\n }\n return 0;\n}\n\n/**\n * The helper function for merge sort which creates the sorted array\n * from the two halves of the input array.\n *\n * @param {Array} arr - The target array which needs to be merged.\n * @param {number} lo - The starting index of the first array half.\n * @param {number} mid - The ending index of the first array half.\n * @param {number} hi - The ending index of the second array half.\n * @param {Function} sortFn - The sort function.\n */\nfunction merge (arr, lo, mid, hi, sortFn) {\n const mainArr = arr;\n const auxArr = [];\n for (let i = lo; i <= hi; i += 1) {\n auxArr[i] = mainArr[i];\n }\n let a = lo;\n let b = mid + 1;\n\n for (let i = lo; i <= hi; i += 1) {\n if (a > mid) {\n mainArr[i] = auxArr[b];\n b += 1;\n } else if (b > hi) {\n mainArr[i] = auxArr[a];\n a += 1;\n } else if (sortFn(auxArr[a], auxArr[b]) <= 0) {\n mainArr[i] = auxArr[a];\n a += 1;\n } else {\n mainArr[i] = auxArr[b];\n b += 1;\n }\n }\n}\n\n/**\n * The helper function for merge sort which would be called\n * recursively for sorting the array halves.\n *\n * @param {Array} arr - The target array which needs to be sorted.\n * @param {number} lo - The starting index of the array half.\n * @param {number} hi - The ending index of the array half.\n * @param {Function} sortFn - The sort function.\n * @return {Array} Returns the target array itself.\n */\nfunction sort (arr, lo, hi, sortFn) {\n if (hi === lo) { return arr; }\n\n const mid = lo + Math.floor((hi - lo) / 2);\n sort(arr, lo, mid, sortFn);\n sort(arr, mid + 1, hi, sortFn);\n merge(arr, lo, mid, hi, sortFn);\n\n return arr;\n}\n\n/**\n * The implementation of merge sort.\n * It is used in DataModel for stable sorting as it is not sure\n * what the sorting algorithm used by browsers is stable or not.\n *\n * @param {Array} arr - The target array which needs to be sorted.\n * @param {Function} [sortFn=defSortFn] - The sort function.\n * @return {Array} Returns the input array itself in sorted order.\n */\nexport function mergeSort (arr, sortFn = defSortFn) {\n if (arr.length > 1) {\n sort(arr, 0, arr.length - 1, sortFn);\n }\n return arr;\n}\n","import { DimensionSubtype, MeasureSubtype } from '../enums';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport { mergeSort } from './merge-sort';\nimport { fieldInSchema } from '../helper';\nimport { isCallable, isArray, } from '../utils';\n/**\n * Generates the sorting functions to sort the data of a DataModel instance\n * according to the input data type.\n *\n * @param {string} dataType - The data type e.g. 'measure', 'datetime' etc.\n * @param {string} sortType - The sorting order i.e. 'asc' or 'desc'.\n * @param {integer} index - The index of the data which will be sorted.\n * @return {Function} Returns the the sorting function.\n */\nfunction getSortFn (dataType, sortType, index) {\n let retFunc;\n switch (dataType) {\n case MeasureSubtype.CONTINUOUS:\n case DimensionSubtype.TEMPORAL:\n if (sortType === 'desc') {\n retFunc = (a, b) => b[index] - a[index];\n } else {\n retFunc = (a, b) => a[index] - b[index];\n }\n break;\n default:\n retFunc = (a, b) => {\n const a1 = `${a[index]}`;\n const b1 = `${b[index]}`;\n if (a1 < b1) {\n return sortType === 'desc' ? 1 : -1;\n }\n if (a1 > b1) {\n return sortType === 'desc' ? -1 : 1;\n }\n return 0;\n };\n }\n return retFunc;\n}\n\n/**\n * Groups the data according to the specified target field.\n *\n * @param {Array} data - The input data array.\n * @param {number} fieldIndex - The target field index within schema array.\n * @return {Array} Returns an array containing the grouped data.\n */\nfunction groupData(data, fieldIndex) {\n const hashMap = new Map();\n const groupedData = [];\n\n data.forEach((datum) => {\n const fieldVal = datum[fieldIndex];\n if (hashMap.has(fieldVal)) {\n groupedData[hashMap.get(fieldVal)][1].push(datum);\n } else {\n groupedData.push([fieldVal, [datum]]);\n hashMap.set(fieldVal, groupedData.length - 1);\n }\n });\n\n return groupedData;\n}\n\n/**\n * Creates the argument value used for sorting function when sort is done\n * with another fields.\n *\n * @param {Array} groupedDatum - The grouped datum for a single dimension field value.\n * @param {Array} targetFields - An array of the sorting fields.\n * @param {Array} targetFieldDetails - An array of the sorting field details in schema.\n * @return {Object} Returns an object containing the value of sorting fields and the target field name.\n */\nfunction createSortingFnArg(groupedDatum, targetFields, targetFieldDetails) {\n const arg = {\n label: groupedDatum[0]\n };\n\n targetFields.reduce((acc, next, idx) => {\n acc[next] = groupedDatum[1].map(datum => datum[targetFieldDetails[idx].index]);\n return acc;\n }, arg);\n\n return arg;\n}\n\n/**\n * Sorts the data before return in dataBuilder.\n *\n * @param {Object} dataObj - An object containing the data and schema.\n * @param {Array} sortingDetails - An array containing the sorting configs.\n */\nfunction sortData(dataObj, sortingDetails) {\n const { data, schema } = dataObj;\n let fieldName;\n let sortMeta;\n let fDetails;\n let i = sortingDetails.length - 1;\n\n for (; i >= 0; i--) {\n fieldName = sortingDetails[i][0];\n sortMeta = sortingDetails[i][1];\n fDetails = fieldInSchema(schema, fieldName);\n\n if (!fDetails) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n if (isCallable(sortMeta)) {\n // eslint-disable-next-line no-loop-func\n mergeSort(data, (a, b) => sortMeta(a[fDetails.index], b[fDetails.index]));\n } else if (isArray(sortMeta)) {\n const groupedData = groupData(data, fDetails.index);\n const sortingFn = sortMeta[sortMeta.length - 1];\n const targetFields = sortMeta.slice(0, sortMeta.length - 1);\n const targetFieldDetails = targetFields.map(f => fieldInSchema(schema, f));\n\n groupedData.forEach((groupedDatum) => {\n groupedDatum.push(createSortingFnArg(groupedDatum, targetFields, targetFieldDetails));\n });\n\n mergeSort(groupedData, (a, b) => {\n const m = a[2];\n const n = b[2];\n return sortingFn(m, n);\n });\n\n // Empty the array\n data.length = 0;\n groupedData.forEach((datum) => {\n data.push(...datum[1]);\n });\n } else {\n sortMeta = String(sortMeta).toLowerCase() === 'desc' ? 'desc' : 'asc';\n mergeSort(data, getSortFn(fDetails.type, sortMeta, fDetails.index));\n }\n }\n\n dataObj.uids = [];\n data.forEach((value) => {\n dataObj.uids.push(value.pop());\n });\n}\n\n\n/**\n * Builds the actual data array.\n *\n * @param {Array} fieldStore - An array of field.\n * @param {string} rowDiffset - A string consisting of which rows to be included eg. '0-2,4,6';\n * @param {string} colIdentifier - A string consisting of the details of which column\n * to be included eg 'date,sales,profit';\n * @param {Object} sortingDetails - An object containing the sorting details of the DataModel instance.\n * @param {Object} options - The options required to create the type of the data.\n * @return {Object} Returns an object containing the multidimensional array and the relative schema.\n */\nexport function dataBuilder (fieldStore, rowDiffset, colIdentifier, sortingDetails, options) {\n const defOptions = {\n addUid: false,\n columnWise: false\n };\n options = Object.assign({}, defOptions, options);\n\n const retObj = {\n schema: [],\n data: [],\n uids: []\n };\n const addUid = options.addUid;\n const reqSorting = sortingDetails && sortingDetails.length > 0;\n // It stores the fields according to the colIdentifier argument\n const tmpDataArr = [];\n // Stores the fields according to the colIdentifier argument\n const colIArr = colIdentifier.split(',');\n\n colIArr.forEach((colName) => {\n for (let i = 0; i < fieldStore.length; i += 1) {\n if (fieldStore[i].name() === colName) {\n tmpDataArr.push(fieldStore[i]);\n break;\n }\n }\n });\n\n // Inserts the schema to the schema object\n tmpDataArr.forEach((field) => {\n /** @todo Need to use extend2 here otherwise user can overwrite the schema. */\n retObj.schema.push(field.schema());\n });\n\n if (addUid) {\n retObj.schema.push({\n name: 'uid',\n type: 'identifier'\n });\n }\n\n rowDiffsetIterator(rowDiffset, (i) => {\n retObj.data.push([]);\n const insertInd = retObj.data.length - 1;\n let start = 0;\n tmpDataArr.forEach((field, ii) => {\n retObj.data[insertInd][ii + start] = field.partialField.data[i];\n });\n if (addUid) {\n retObj.data[insertInd][tmpDataArr.length] = i;\n }\n // Creates an array of unique identifiers for each row\n retObj.uids.push(i);\n\n // If sorting needed then there is the need to expose the index\n // mapping from the old index to its new index\n if (reqSorting) { retObj.data[insertInd].push(i); }\n });\n\n // Handles the sort functionality\n if (reqSorting) {\n sortData(retObj, sortingDetails);\n }\n\n if (options.columnWise) {\n const tmpData = Array(...Array(retObj.schema.length)).map(() => []);\n retObj.data.forEach((tuple) => {\n tuple.forEach((data, i) => {\n tmpData[i].push(data);\n });\n });\n retObj.data = tmpData;\n }\n\n return retObj;\n}\n","import DataModel from '../datamodel';\nimport { extend2 } from '../utils';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport { isArrEqual } from '../utils/helper';\n\n/**\n * Performs the union operation between two dm instances.\n *\n * @todo Fix the conflicts between union and difference terminology here.\n *\n * @param {dm} dm1 - The first dm instance.\n * @param {dm} dm2 - The second dm instance.\n * @return {dm} Returns the newly created dm after union operation.\n */\nexport function difference (dm1, dm2) {\n const hashTable = {};\n const schema = [];\n const schemaNameArr = [];\n const data = [];\n const dm1FieldStore = dm1.getFieldspace();\n const dm2FieldStore = dm2.getFieldspace();\n const dm1FieldStoreFieldObj = dm1FieldStore.fieldsObj();\n const dm2FieldStoreFieldObj = dm2FieldStore.fieldsObj();\n const name = `${dm1FieldStore.name} union ${dm2FieldStore.name}`;\n\n // For union the columns should match otherwise return a clone of the dm1\n if (!isArrEqual(dm1._colIdentifier.split(',').sort(), dm2._colIdentifier.split(',').sort())) {\n return null;\n }\n\n // Prepare the schema\n (dm1._colIdentifier.split(',')).forEach((fieldName) => {\n const field = dm1FieldStoreFieldObj[fieldName];\n schema.push(extend2({}, field.schema()));\n schemaNameArr.push(field.schema().name);\n });\n\n /**\n * The helper function to create the data.\n *\n * @param {dm} dm - The dm instance for which the data is inserted.\n * @param {Object} fieldsObj - The fieldStore object format.\n * @param {boolean} addData - If true only tuple will be added to the data.\n */\n function prepareDataHelper(dm, fieldsObj, addData) {\n rowDiffsetIterator(dm._rowDiffset, (i) => {\n const tuple = {};\n let hashData = '';\n schemaNameArr.forEach((schemaName) => {\n const value = fieldsObj[schemaName].partialField.data[i];\n hashData += `-${value}`;\n tuple[schemaName] = value;\n });\n if (!hashTable[hashData]) {\n if (addData) { data.push(tuple); }\n hashTable[hashData] = true;\n }\n });\n }\n\n // Prepare the data\n prepareDataHelper(dm2, dm2FieldStoreFieldObj, false);\n prepareDataHelper(dm1, dm1FieldStoreFieldObj, true);\n\n return new DataModel(data, schema, { name });\n}\n\n","import { isArray } from '../utils';\nimport InvalidAwareTypes from '../invalid-aware-types';\nimport { GROUP_BY_FUNCTIONS } from '../enums';\n\nconst { SUM, AVG, FIRST, LAST, COUNT, STD, MIN, MAX } = GROUP_BY_FUNCTIONS;\n\nfunction getFilteredValues(arr) {\n return arr.filter(item => !(item instanceof InvalidAwareTypes));\n}\n/**\n * Reducer function that returns the sum of all the values.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the sum of the array.\n */\nfunction sum (arr) {\n if (isArray(arr) && !(arr[0] instanceof Array)) {\n const filteredNumber = getFilteredValues(arr);\n const totalSum = filteredNumber.length ?\n filteredNumber.reduce((acc, curr) => acc + curr, 0)\n : InvalidAwareTypes.NULL;\n return totalSum;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Reducer function that returns the average of all the values.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the mean value of the array.\n */\nfunction avg (arr) {\n if (isArray(arr) && !(arr[0] instanceof Array)) {\n const totalSum = sum(arr);\n const len = arr.length || 1;\n return (Number.isNaN(totalSum) || totalSum instanceof InvalidAwareTypes) ?\n InvalidAwareTypes.NULL : totalSum / len;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Reducer function that gives the min value amongst all the values.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the minimum value of the array.\n */\nfunction min (arr) {\n if (isArray(arr) && !(arr[0] instanceof Array)) {\n // Filter out undefined, null and NaN values\n const filteredValues = getFilteredValues(arr);\n\n return (filteredValues.length) ? Math.min(...filteredValues) : InvalidAwareTypes.NULL;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Reducer function that gives the max value amongst all the values.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the maximum value of the array.\n */\nfunction max (arr) {\n if (isArray(arr) && !(arr[0] instanceof Array)) {\n // Filter out undefined, null and NaN values\n const filteredValues = getFilteredValues(arr);\n\n return (filteredValues.length) ? Math.max(...filteredValues) : InvalidAwareTypes.NULL;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Reducer function that gives the first value of the array.\n *\n * @public\n * @param {Array} arr - The input array.\n * @return {number} Returns the first value of the array.\n */\nfunction first (arr) {\n return arr[0];\n}\n\n/**\n * Reducer function that gives the last value of the array.\n *\n * @public\n * @param {Array} arr - The input array.\n * @return {number} Returns the last value of the array.\n */\nfunction last (arr) {\n return arr[arr.length - 1];\n}\n\n/**\n * Reducer function that gives the count value of the array.\n *\n * @public\n * @param {Array} arr - The input array.\n * @return {number} Returns the length of the array.\n */\nfunction count (arr) {\n if (isArray(arr)) {\n return arr.length;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Calculates the variance of the input array.\n *\n * @param {Array.} arr - The input array.\n * @return {number} Returns the variance of the input array.\n */\nfunction variance (arr) {\n let mean = avg(arr);\n return avg(arr.map(num => (num - mean) ** 2));\n}\n\n/**\n * Calculates the square root of the variance of the input array.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the square root of the variance.\n */\nfunction std (arr) {\n return Math.sqrt(variance(arr));\n}\n\n\nconst fnList = {\n [SUM]: sum,\n [AVG]: avg,\n [MIN]: min,\n [MAX]: max,\n [FIRST]: first,\n [LAST]: last,\n [COUNT]: count,\n [STD]: std\n};\n\nconst defaultReducerName = SUM;\n\nexport {\n defaultReducerName,\n sum as defReducer,\n fnList,\n};\n","import { defReducer, fnList } from '../operator';\n\n/**\n * A page level storage which stores, registers, unregisters reducers for all the datamodel instances. There is only one\n * reducer store available in a page. All the datamodel instances receive same instance of reducer store. DataModel\n * out of the box provides handful of {@link reducer | reducers} which can be used as reducer funciton.\n *\n * @public\n * @namespace DataModel\n */\nclass ReducerStore {\n constructor () {\n this.store = new Map();\n this.store.set('defReducer', defReducer);\n\n Object.entries(fnList).forEach((key) => {\n this.store.set(key[0], key[1]);\n });\n }\n\n /**\n * Changes the `defaultReducer` globally. For all the fields which does not have `defAggFn` mentioned in schema, the\n * value of `defaultReducer` is used for aggregation.\n *\n * @public\n * @param {string} [reducer='sum'] - The name of the default reducer. It picks up the definition from store by doing\n * name lookup. If no name is found then it takes `sum` as the default reducer.\n * @return {ReducerStore} Returns instance of the singleton store in page.\n */\n defaultReducer (...params) {\n if (!params.length) {\n return this.store.get('defReducer');\n }\n\n let reducer = params[0];\n\n if (typeof reducer === 'function') {\n this.store.set('defReducer', reducer);\n } else {\n reducer = String(reducer);\n if (Object.keys(fnList).indexOf(reducer) !== -1) {\n this.store.set('defReducer', fnList[reducer]);\n } else {\n throw new Error(`Reducer ${reducer} not found in registry`);\n }\n }\n return this;\n }\n\n /**\n *\n * Registers a {@link reducer | reducer}.\n * A {@link reducer | reducer} has to be registered before it is used.\n *\n * @example\n * // find the mean squared value of a given set\n * const reducerStore = DataModel.Reducers();\n *\n * reducers.register('meanSquared', (arr) => {\n * const squaredVal = arr.map(item => item * item);\n * let sum = 0;\n * for (let i = 0, l = squaredVal.length; i < l; i++) {\n * sum += squaredVal[i++];\n * }\n *\n * return sum;\n * })\n *\n * // datamodel (dm) is already prepared with cars.json\n * const dm1 = dm.groupBy(['origin'], {\n * accleration: 'meanSquared'\n * });\n *\n * @public\n *\n * @param {string} name formal name for a reducer. If the given name already exists in store it is overridden by new\n * definition.\n * @param {Function} reducer definition of {@link reducer} function.\n *\n * @return {Function} function for unregistering the reducer.\n */\n register (name, reducer) {\n if (typeof reducer !== 'function') {\n throw new Error('Reducer should be a function');\n }\n\n name = String(name);\n this.store.set(name, reducer);\n\n return () => { this.__unregister(name); };\n }\n\n __unregister (name) {\n if (this.store.has(name)) {\n this.store.delete(name);\n }\n }\n\n resolve (name) {\n if (name instanceof Function) {\n return name;\n }\n return this.store.get(name);\n }\n}\n\nconst reducerStore = (function () {\n let store = null;\n\n function getStore () {\n if (store === null) {\n store = new ReducerStore();\n }\n return store;\n }\n return getStore();\n}());\n\nexport default reducerStore;\n","import { extend2 } from '../utils';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport DataModel from '../export';\nimport reducerStore from '../utils/reducer-store';\nimport { defaultReducerName } from './group-by-function';\nimport { FieldType } from '../enums';\n\n/**\n * This function sanitize the user given field and return a common Array structure field\n * list\n * @param {DataModel} dataModel the dataModel operating on\n * @param {Array} fieldArr user input of field Array\n * @return {Array} arrays of field name\n */\nfunction getFieldArr (dataModel, fieldArr) {\n const retArr = [];\n const fieldStore = dataModel.getFieldspace();\n const dimensions = fieldStore.getDimension();\n\n Object.entries(dimensions).forEach(([key]) => {\n if (fieldArr && fieldArr.length) {\n if (fieldArr.indexOf(key) !== -1) {\n retArr.push(key);\n }\n } else {\n retArr.push(key);\n }\n });\n\n return retArr;\n}\n\n/**\n * This sanitize the reducer provide by the user and create a common type of object.\n * user can give function Also\n * @param {DataModel} dataModel dataModel to worked on\n * @param {Object|function} [reducers={}] reducer provided by the users\n * @return {Object} object containing reducer function for every measure\n */\nfunction getReducerObj (dataModel, reducers = {}) {\n const retObj = {};\n const fieldStore = dataModel.getFieldspace();\n const measures = fieldStore.getMeasure();\n const defReducer = reducerStore.defaultReducer();\n\n Object.keys(measures).forEach((measureName) => {\n if (typeof reducers[measureName] !== 'string') {\n reducers[measureName] = measures[measureName].defAggFn();\n }\n const reducerFn = reducerStore.resolve(reducers[measureName]);\n if (reducerFn) {\n retObj[measureName] = reducerFn;\n } else {\n retObj[measureName] = defReducer;\n reducers[measureName] = defaultReducerName;\n }\n });\n return retObj;\n}\n\n/**\n * main function which perform the group-by operations which reduce the measures value is the\n * fields are common according to the reducer function provided\n * @param {DataModel} dataModel the dataModel to worked\n * @param {Array} fieldArr fields according to which the groupby should be worked\n * @param {Object|Function} reducers reducers function\n * @param {DataModel} existingDataModel Existing datamodel instance\n * @return {DataModel} new dataModel with the group by\n */\nfunction groupBy (dataModel, fieldArr, reducers, existingDataModel) {\n const sFieldArr = getFieldArr(dataModel, fieldArr);\n const reducerObj = getReducerObj(dataModel, reducers);\n const fieldStore = dataModel.getFieldspace();\n const fieldStoreObj = fieldStore.fieldsObj();\n const dbName = fieldStore.name;\n const dimensionArr = [];\n const measureArr = [];\n const schema = [];\n const hashMap = {};\n const data = [];\n let newDataModel;\n\n // Prepare the schema\n Object.entries(fieldStoreObj).forEach(([key, value]) => {\n if (sFieldArr.indexOf(key) !== -1 || reducerObj[key]) {\n schema.push(extend2({}, value.schema()));\n\n switch (value.schema().type) {\n case FieldType.MEASURE:\n measureArr.push(key);\n break;\n default:\n case FieldType.DIMENSION:\n dimensionArr.push(key);\n }\n }\n });\n // Prepare the data\n let rowCount = 0;\n rowDiffsetIterator(dataModel._rowDiffset, (i) => {\n let hash = '';\n dimensionArr.forEach((_) => {\n hash = `${hash}-${fieldStoreObj[_].partialField.data[i]}`;\n });\n if (hashMap[hash] === undefined) {\n hashMap[hash] = rowCount;\n data.push({});\n dimensionArr.forEach((_) => {\n data[rowCount][_] = fieldStoreObj[_].partialField.data[i];\n });\n measureArr.forEach((_) => {\n data[rowCount][_] = [fieldStoreObj[_].partialField.data[i]];\n });\n rowCount += 1;\n } else {\n measureArr.forEach((_) => {\n data[hashMap[hash]][_].push(fieldStoreObj[_].partialField.data[i]);\n });\n }\n });\n\n // reduction\n let cachedStore = {};\n let cloneProvider = () => dataModel.detachedRoot();\n data.forEach((row) => {\n const tuple = row;\n measureArr.forEach((_) => {\n tuple[_] = reducerObj[_](row[_], cloneProvider, cachedStore);\n });\n });\n if (existingDataModel) {\n existingDataModel.__calculateFieldspace();\n newDataModel = existingDataModel;\n }\n else {\n newDataModel = new DataModel(data, schema, { name: dbName });\n }\n return newDataModel;\n}\n\nexport { groupBy, getFieldArr, getReducerObj };\n","import { getCommonSchema } from './get-common-schema';\n\n/**\n * The filter function used in natural join.\n * It generates a function that will have the logic to join two\n * DataModel instances by the process of natural join.\n *\n * @param {DataModel} dm1 - The left DataModel instance.\n * @param {DataModel} dm2 - The right DataModel instance.\n * @return {Function} Returns a function that is used in cross-product operation.\n */\nexport function naturalJoinFilter (dm1, dm2) {\n const dm1FieldStore = dm1.getFieldspace();\n const dm2FieldStore = dm2.getFieldspace();\n // const dm1FieldStoreName = dm1FieldStore.name;\n // const dm2FieldStoreName = dm2FieldStore.name;\n const commonSchemaArr = getCommonSchema(dm1FieldStore, dm2FieldStore);\n\n return (dm1Fields, dm2Fields) => {\n let retainTuple = true;\n commonSchemaArr.forEach((fieldName) => {\n if (dm1Fields[fieldName].value ===\n dm2Fields[fieldName].value && retainTuple) {\n retainTuple = true;\n } else {\n retainTuple = false;\n }\n });\n return retainTuple;\n };\n}\n","import DataModel from '../export';\nimport { extend2 } from '../utils';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport { isArrEqual } from '../utils/helper';\n/**\n * Performs the union operation between two dm instances.\n *\n * @param {dm} dm1 - The first dm instance.\n * @param {dm} dm2 - The second dm instance.\n * @return {dm} Returns the newly created dm after union operation.\n */\nexport function union (dm1, dm2) {\n const hashTable = {};\n const schema = [];\n const schemaNameArr = [];\n const data = [];\n const dm1FieldStore = dm1.getFieldspace();\n const dm2FieldStore = dm2.getFieldspace();\n const dm1FieldStoreFieldObj = dm1FieldStore.fieldsObj();\n const dm2FieldStoreFieldObj = dm2FieldStore.fieldsObj();\n const name = `${dm1FieldStore.name} union ${dm2FieldStore.name}`;\n\n // For union the columns should match otherwise return a clone of the dm1\n if (!isArrEqual(dm1._colIdentifier.split(',').sort(), dm2._colIdentifier.split(',').sort())) {\n return null;\n }\n\n // Prepare the schema\n (dm1._colIdentifier.split(',')).forEach((fieldName) => {\n const field = dm1FieldStoreFieldObj[fieldName];\n schema.push(extend2({}, field.schema()));\n schemaNameArr.push(field.schema().name);\n });\n\n /**\n * The helper function to create the data.\n *\n * @param {dm} dm - The dm instance for which the data is inserted.\n * @param {Object} fieldsObj - The fieldStore object format.\n */\n function prepareDataHelper (dm, fieldsObj) {\n rowDiffsetIterator(dm._rowDiffset, (i) => {\n const tuple = {};\n let hashData = '';\n schemaNameArr.forEach((schemaName) => {\n const value = fieldsObj[schemaName].partialField.data[i];\n hashData += `-${value}`;\n tuple[schemaName] = value;\n });\n if (!hashTable[hashData]) {\n data.push(tuple);\n hashTable[hashData] = true;\n }\n });\n }\n\n // Prepare the data\n prepareDataHelper(dm1, dm1FieldStoreFieldObj);\n prepareDataHelper(dm2, dm2FieldStoreFieldObj);\n\n return new DataModel(data, schema, { name });\n}\n","import { crossProduct } from './cross-product';\nimport { JOINS } from '../constants';\nimport { union } from './union';\n\n\nexport function leftOuterJoin (dataModel1, dataModel2, filterFn) {\n return crossProduct(dataModel1, dataModel2, filterFn, false, JOINS.LEFTOUTER);\n}\n\nexport function rightOuterJoin (dataModel1, dataModel2, filterFn) {\n return crossProduct(dataModel2, dataModel1, filterFn, false, JOINS.RIGHTOUTER);\n}\n\nexport function fullOuterJoin (dataModel1, dataModel2, filterFn) {\n return union(leftOuterJoin(dataModel1, dataModel2, filterFn), rightOuterJoin(dataModel1, dataModel2, filterFn));\n}\n","import { rowDiffsetIterator } from '../../operator/row-diffset-iterator';\n\n/**\n * In {@link DataModel}, every tabular data consists of column, a column is stored as field.\n * Field contains all the data for a given column in an array.\n *\n * Each record consists of several fields; the fields of all records form the columns.\n * Examples of fields: name, gender, sex etc.\n *\n * In DataModel, each field can have multiple attributes which describes its data and behaviour.\n * A field can have two types of data: Measure and Dimension.\n *\n * A Dimension Field is the context on which a data is categorized and the measure is the numerical values that\n * quantify the data set.\n * In short a dimension is the lens through which you are looking at your measure data.\n *\n * Refer to {@link Schema} to get info about possible field attributes.\n *\n * @public\n * @class\n */\nexport default class Field {\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {PartialField} partialField - The partialField instance which holds the whole data.\n * @param {string} rowDiffset - The data subset definition.\n */\n constructor (partialField, rowDiffset) {\n this.partialField = partialField;\n this.rowDiffset = rowDiffset;\n }\n\n /**\n * Generates the field type specific domain.\n *\n * @public\n * @abstract\n */\n domain () {\n throw new Error('Not yet implemented');\n }\n\n /**\n * Returns the the field schema.\n *\n * @public\n * @return {string} Returns the field schema.\n */\n schema () {\n return this.partialField.schema;\n }\n\n /**\n * Returns the name of the field.\n *\n * @public\n * @return {string} Returns the name of the field.\n */\n name () {\n return this.partialField.name;\n }\n\n /**\n * Returns the type of the field.\n *\n * @public\n * @return {string} Returns the type of the field.\n */\n type () {\n return this.partialField.schema.type;\n }\n\n /**\n * Returns the subtype of the field.\n *\n * @public\n * @return {string} Returns the subtype of the field.\n */\n subtype () {\n return this.partialField.schema.subtype;\n }\n\n /**\n * Returns the description of the field.\n *\n * @public\n * @return {string} Returns the description of the field.\n */\n description () {\n return this.partialField.schema.description;\n }\n\n /**\n * Returns the display name of the field.\n *\n * @public\n * @return {string} Returns the display name of the field.\n */\n displayName () {\n return this.partialField.schema.displayName || this.partialField.schema.name;\n }\n\n /**\n * Returns the data associated with the field.\n *\n * @public\n * @return {Array} Returns the data.\n */\n data () {\n const data = [];\n rowDiffsetIterator(this.rowDiffset, (i) => {\n data.push(this.partialField.data[i]);\n });\n return data;\n }\n\n /**\n * Returns the formatted version of the underlying field data.\n *\n * @public\n * @abstract\n */\n formattedData () {\n throw new Error('Not yet implemented');\n }\n}\n","import Field from '../field';\n\n/**\n * Represents dimension field type.\n *\n * @public\n * @class\n * @extends Field\n */\nexport default class Dimension extends Field {\n /**\n * Returns the domain for the dimension field.\n *\n * @override\n * @public\n * @return {any} Returns the calculated domain.\n */\n domain () {\n if (!this._cachedDomain) {\n this._cachedDomain = this.calculateDataDomain();\n }\n return this._cachedDomain;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @abstract\n */\n calculateDataDomain () {\n throw new Error('Not yet implemented');\n }\n\n /**\n * Returns the formatted version of the underlying field data.\n *\n * @public\n * @override\n * @return {Array} Returns the formatted data.\n */\n formattedData () {\n return this.data();\n }\n}\n","import { rowDiffsetIterator } from '../../operator/row-diffset-iterator';\nimport { DimensionSubtype } from '../../enums';\nimport Dimension from '../dimension';\n/**\n * Represents categorical field subtype.\n *\n * @public\n * @class\n * @extends Dimension\n */\nexport default class Categorical extends Dimension {\n /**\n * Returns the subtype of the field.\n *\n * @public\n * @override\n * @return {string} Returns the subtype of the field.\n */\n subtype () {\n return DimensionSubtype.CATEGORICAL;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @override\n * @return {Array} Returns the unique values.\n */\n calculateDataDomain () {\n const hash = new Set();\n const domain = [];\n\n // here don't use this.data() as the iteration will be occurred two times on same data.\n rowDiffsetIterator(this.rowDiffset, (i) => {\n const datum = this.partialField.data[i];\n if (!hash.has(datum)) {\n hash.add(datum);\n domain.push(datum);\n }\n });\n return domain;\n }\n}\n","import { rowDiffsetIterator } from '../../operator/row-diffset-iterator';\nimport Dimension from '../dimension';\nimport { DateTimeFormatter } from '../../utils';\nimport InvalidAwareTypes from '../../invalid-aware-types';\n\n/**\n * Represents temporal field subtype.\n *\n * @public\n * @class\n * @extends Dimension\n */\nexport default class Temporal extends Dimension {\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {PartialField} partialField - The partialField instance which holds the whole data.\n * @param {string} rowDiffset - The data subset definition.\n */\n constructor (partialField, rowDiffset) {\n super(partialField, rowDiffset);\n\n this._cachedMinDiff = null;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @override\n * @return {Array} Returns the unique values.\n */\n calculateDataDomain () {\n const hash = new Set();\n const domain = [];\n\n // here don't use this.data() as the iteration will be\n // occurred two times on same data.\n rowDiffsetIterator(this.rowDiffset, (i) => {\n const datum = this.partialField.data[i];\n if (!hash.has(datum)) {\n hash.add(datum);\n domain.push(datum);\n }\n });\n\n return domain;\n }\n\n\n /**\n * Calculates the minimum consecutive difference from the associated field data.\n *\n * @public\n * @return {number} Returns the minimum consecutive diff in milliseconds.\n */\n minimumConsecutiveDifference () {\n if (this._cachedMinDiff) {\n return this._cachedMinDiff;\n }\n\n const sortedData = this.data().filter(item => !(item instanceof InvalidAwareTypes)).sort((a, b) => a - b);\n const arrLn = sortedData.length;\n let minDiff = Number.POSITIVE_INFINITY;\n let prevDatum;\n let nextDatum;\n let processedCount = 0;\n\n for (let i = 1; i < arrLn; i++) {\n prevDatum = sortedData[i - 1];\n nextDatum = sortedData[i];\n\n if (nextDatum === prevDatum) {\n continue;\n }\n\n minDiff = Math.min(minDiff, nextDatum - sortedData[i - 1]);\n processedCount++;\n }\n\n if (!processedCount) {\n minDiff = null;\n }\n this._cachedMinDiff = minDiff;\n\n return this._cachedMinDiff;\n }\n\n /**\n * Returns the format specified in the input schema while creating field.\n *\n * @public\n * @return {string} Returns the datetime format.\n */\n format () {\n return this.partialField.schema.format;\n }\n\n /**\n * Returns the formatted version of the underlying field data.\n *\n * @public\n * @override\n * @return {Array} Returns the formatted data.\n */\n formattedData () {\n const data = [];\n rowDiffsetIterator(this.rowDiffset, (i) => {\n const datum = this.partialField.data[i];\n if (datum instanceof InvalidAwareTypes) {\n data.push(datum);\n } else {\n data.push(DateTimeFormatter.formatAs(datum, this.format()));\n }\n });\n return data;\n }\n}\n\n","import Dimension from '../dimension';\n\n/**\n * Represents binned field subtype.\n *\n * @public\n * @class\n * @extends Dimension\n */\nexport default class Binned extends Dimension {\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @override\n * @return {Array} Returns the last and first values of bins config array.\n */\n calculateDataDomain () {\n const binsArr = this.partialField.schema.bins;\n return [binsArr[0], binsArr[binsArr.length - 1]];\n }\n\n /**\n * Returns the bins config provided while creating the field instance.\n *\n * @public\n * @return {Array} Returns the bins array config.\n */\n bins () {\n return this.partialField.schema.bins;\n }\n}\n","import { formatNumber } from '../../utils';\nimport { defaultReducerName } from '../../operator/group-by-function';\nimport Field from '../field';\n\n/**\n * Represents measure field type.\n *\n * @public\n * @class\n * @extends Field\n */\nexport default class Measure extends Field {\n /**\n * Returns the domain for the measure field.\n *\n * @override\n * @public\n * @return {any} Returns the calculated domain.\n */\n domain () {\n if (!this._cachedDomain) {\n this._cachedDomain = this.calculateDataDomain();\n }\n return this._cachedDomain;\n }\n\n /**\n * Returns the unit of the measure field.\n *\n * @public\n * @return {string} Returns unit of the field.\n */\n unit () {\n return this.partialField.schema.unit;\n }\n\n /**\n * Returns the aggregation function name of the measure field.\n *\n * @public\n * @return {string} Returns aggregation function name of the field.\n */\n defAggFn () {\n return this.partialField.schema.defAggFn || defaultReducerName;\n }\n\n /**\n * Returns the number format of the measure field.\n *\n * @public\n * @return {Function} Returns number format of the field.\n */\n numberFormat () {\n const { numberFormat } = this.partialField.schema;\n return numberFormat instanceof Function ? numberFormat : formatNumber;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @abstract\n */\n calculateDataDomain () {\n throw new Error('Not yet implemented');\n }\n\n /**\n * Returns the formatted version of the underlying field data.\n *\n * @public\n * @override\n * @return {Array} Returns the formatted data.\n */\n formattedData () {\n return this.data();\n }\n}\n","import { rowDiffsetIterator } from '../../operator/row-diffset-iterator';\nimport { MeasureSubtype } from '../../enums';\nimport Measure from '../measure';\nimport InvalidAwareTypes from '../../invalid-aware-types';\n\n/**\n * Represents continuous field subtype.\n *\n * @public\n * @class\n * @extends Measure\n */\nexport default class Continuous extends Measure {\n /**\n * Returns the subtype of the field.\n *\n * @public\n * @override\n * @return {string} Returns the subtype of the field.\n */\n subtype () {\n return MeasureSubtype.CONTINUOUS;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @override\n * @return {Array} Returns the min and max values.\n */\n calculateDataDomain () {\n let min = Number.POSITIVE_INFINITY;\n let max = Number.NEGATIVE_INFINITY;\n\n // here don't use this.data() as the iteration will be occurred two times on same data.\n rowDiffsetIterator(this.rowDiffset, (i) => {\n const datum = this.partialField.data[i];\n if (datum instanceof InvalidAwareTypes) {\n return;\n }\n\n if (datum < min) {\n min = datum;\n }\n if (datum > max) {\n max = datum;\n }\n });\n\n return [min, max];\n }\n}\n","/**\n * A interface to represent a parser which is responsible to parse the field.\n *\n * @public\n * @interface\n */\nexport default class FieldParser {\n /**\n * Parses a single value of a field and return the sanitized form.\n *\n * @public\n * @abstract\n */\n parse () {\n throw new Error('Not yet implemented');\n }\n}\n","import FieldParser from '../field-parser';\nimport InvalidAwareTypes from '../../../invalid-aware-types';\n\n/**\n * A FieldParser which parses the categorical values.\n *\n * @public\n * @class\n * @implements {FieldParser}\n */\nexport default class CategoricalParser extends FieldParser {\n /**\n * Parses a single value of a field and returns the stringified form.\n *\n * @public\n * @param {string|number} val - The value of the field.\n * @return {string} Returns the stringified value.\n */\n parse (val) {\n let result;\n // check if invalid date value\n if (!InvalidAwareTypes.isInvalid(val)) {\n result = String(val).trim();\n } else {\n result = InvalidAwareTypes.getInvalidType(val);\n }\n return result;\n }\n}\n","import { DateTimeFormatter } from '../../../utils';\nimport FieldParser from '../field-parser';\nimport InvalidAwareTypes from '../../../invalid-aware-types';\n\n/**\n * A FieldParser which parses the temporal values.\n *\n * @public\n * @class\n * @implements {FieldParser}\n */\nexport default class TemporalParser extends FieldParser {\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {Object} schema - The schema object for the corresponding field.\n */\n constructor (schema) {\n super();\n this.schema = schema;\n this._dtf = new DateTimeFormatter(this.schema.format);\n }\n\n /**\n * Parses a single value of a field and returns the millisecond value.\n *\n * @public\n * @param {string|number} val - The value of the field.\n * @return {number} Returns the millisecond value.\n */\n parse (val) {\n let result;\n // check if invalid date value\n if (!InvalidAwareTypes.isInvalid(val)) {\n let nativeDate = this._dtf.getNativeDate(val);\n result = nativeDate ? nativeDate.getTime() : InvalidAwareTypes.NA;\n } else {\n result = InvalidAwareTypes.getInvalidType(val);\n }\n return result;\n }\n}\n","import FieldParser from '../field-parser';\nimport InvalidAwareTypes from '../../../invalid-aware-types';\n\n/**\n * A FieldParser which parses the binned values.\n *\n * @public\n * @class\n * @implements {FieldParser}\n */\nexport default class BinnedParser extends FieldParser {\n /**\n * Parses a single binned value of a field and returns the sanitized value.\n *\n * @public\n * @param {string} val - The value of the field.\n * @return {string} Returns the sanitized value.\n */\n parse (val) {\n const regex = /^\\s*([+-]?\\d+(?:\\.\\d+)?)\\s*-\\s*([+-]?\\d+(?:\\.\\d+)?)\\s*$/;\n val = String(val);\n let result;\n // check if invalid date value\n if (!InvalidAwareTypes.isInvalid(val)) {\n let matched = val.match(regex);\n result = matched ? `${Number.parseFloat(matched[1])}-${Number.parseFloat(matched[2])}`\n : InvalidAwareTypes.NA;\n } else {\n result = InvalidAwareTypes.getInvalidType(val);\n }\n return result;\n }\n}\n","import FieldParser from '../field-parser';\nimport InvalidAwareTypes from '../../../invalid-aware-types';\n\n/**\n * A FieldParser which parses the continuous values.\n *\n * @public\n * @class\n * @implements {FieldParser}\n */\nexport default class ContinuousParser extends FieldParser {\n /**\n * Parses a single value of a field and returns the number form.\n *\n * @public\n * @param {string|number} val - The value of the field.\n * @return {string} Returns the number value.\n */\n parse (val) {\n let result;\n // check if invalid date value\n if (!InvalidAwareTypes.isInvalid(val)) {\n let parsedVal = parseFloat(val, 10);\n result = Number.isNaN(parsedVal) ? InvalidAwareTypes.NA : parsedVal;\n } else {\n result = InvalidAwareTypes.getInvalidType(val);\n }\n return result;\n }\n}\n","/**\n * Stores the full data and the metadata of a field. It provides\n * a single source of data from which the future Field\n * instance can get a subset of it with a rowDiffset config.\n *\n * @class\n * @public\n */\nexport default class PartialField {\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {string} name - The name of the field.\n * @param {Array} data - The data array.\n * @param {Object} schema - The schema object of the corresponding field.\n * @param {FieldParser} parser - The parser instance corresponding to that field.\n */\n constructor (name, data, schema, parser) {\n this.name = name;\n this.schema = schema;\n this.parser = parser;\n this.data = this._sanitize(data);\n }\n\n /**\n * Sanitizes the field data.\n *\n * @private\n * @param {Array} data - The actual input data.\n * @return {Array} Returns the sanitized data.\n */\n _sanitize (data) {\n return data.map(datum => this.parser.parse(datum));\n }\n}\n","import { FieldType, DimensionSubtype, MeasureSubtype } from './enums';\nimport {\n Categorical,\n Temporal,\n Binned,\n Continuous,\n CategoricalParser,\n TemporalParser,\n BinnedParser,\n ContinuousParser,\n PartialField\n} from './fields';\n\n/**\n * Creates a field instance according to the provided data and schema.\n *\n * @param {Array} data - The field data array.\n * @param {Object} schema - The field schema object.\n * @return {Field} Returns the newly created field instance.\n */\nfunction createUnitField(data, schema) {\n data = data || [];\n let partialField;\n\n switch (schema.type) {\n case FieldType.MEASURE:\n switch (schema.subtype) {\n case MeasureSubtype.CONTINUOUS:\n partialField = new PartialField(schema.name, data, schema, new ContinuousParser());\n return new Continuous(partialField, `0-${data.length - 1}`);\n default:\n partialField = new PartialField(schema.name, data, schema, new ContinuousParser());\n return new Continuous(partialField, `0-${data.length - 1}`);\n }\n case FieldType.DIMENSION:\n switch (schema.subtype) {\n case DimensionSubtype.CATEGORICAL:\n partialField = new PartialField(schema.name, data, schema, new CategoricalParser());\n return new Categorical(partialField, `0-${data.length - 1}`);\n case DimensionSubtype.TEMPORAL:\n partialField = new PartialField(schema.name, data, schema, new TemporalParser(schema));\n return new Temporal(partialField, `0-${data.length - 1}`);\n case DimensionSubtype.BINNED:\n partialField = new PartialField(schema.name, data, schema, new BinnedParser());\n return new Binned(partialField, `0-${data.length - 1}`);\n default:\n partialField = new PartialField(schema.name, data, schema, new CategoricalParser());\n return new Categorical(partialField, `0-${data.length - 1}`);\n }\n default:\n partialField = new PartialField(schema.name, data, schema, new CategoricalParser());\n return new Categorical(partialField, `0-${data.length - 1}`);\n }\n}\n\n\n/**\n * Creates a field instance from partialField and rowDiffset.\n *\n * @param {PartialField} partialField - The corresponding partial field.\n * @param {string} rowDiffset - The data subset config.\n * @return {Field} Returns the newly created field instance.\n */\nexport function createUnitFieldFromPartial(partialField, rowDiffset) {\n const { schema } = partialField;\n\n switch (schema.type) {\n case FieldType.MEASURE:\n switch (schema.subtype) {\n case MeasureSubtype.CONTINUOUS:\n return new Continuous(partialField, rowDiffset);\n default:\n return new Continuous(partialField, rowDiffset);\n }\n case FieldType.DIMENSION:\n switch (schema.subtype) {\n case DimensionSubtype.CATEGORICAL:\n return new Categorical(partialField, rowDiffset);\n case DimensionSubtype.TEMPORAL:\n return new Temporal(partialField, rowDiffset);\n case DimensionSubtype.BINNED:\n return new Binned(partialField, rowDiffset);\n default:\n return new Categorical(partialField, rowDiffset);\n }\n default:\n return new Categorical(partialField, rowDiffset);\n }\n}\n\n/**\n * Creates the field instances with input data and schema.\n *\n * @param {Array} dataColumn - The data array for fields.\n * @param {Array} schema - The schema array for fields.\n * @param {Array} headers - The array of header names.\n * @return {Array.} Returns an array of newly created field instances.\n */\nexport function createFields(dataColumn, schema, headers) {\n const headersObj = {};\n\n if (!(headers && headers.length)) {\n headers = schema.map(item => item.name);\n }\n\n headers.forEach((header, i) => {\n headersObj[header] = i;\n });\n\n return schema.map(item => createUnitField(dataColumn[headersObj[item.name]], item));\n}\n","import { DataFormat } from './enums';\n\nexport default {\n dataFormat: DataFormat.AUTO\n};\n","import { columnMajor } from '../utils';\n\n/**\n * Parses and converts data formatted in DSV array to a manageable internal format.\n *\n * @param {Array.} arr - A 2D array containing of the DSV data.\n * @param {Object} options - Option to control the behaviour of the parsing.\n * @param {boolean} [options.firstRowHeader=true] - Whether the first row of the dsv data is header or not.\n * @return {Array} Returns an array of headers and column major data.\n * @example\n *\n * // Sample input data:\n * const data = [\n * [\"a\", \"b\", \"c\"],\n * [1, 2, 3],\n * [4, 5, 6],\n * [7, 8, 9]\n * ];\n */\nfunction DSVArr (arr, options) {\n const defaultOption = {\n firstRowHeader: true,\n };\n options = Object.assign({}, defaultOption, options);\n\n let header;\n const columns = [];\n const push = columnMajor(columns);\n\n if (options.firstRowHeader) {\n // If header present then mutate the array.\n // Do in-place mutation to save space.\n header = arr.splice(0, 1)[0];\n } else {\n header = [];\n }\n\n arr.forEach(field => push(...field));\n\n return [header, columns];\n}\n\nexport default DSVArr;\n","var EOL = {},\n EOF = {},\n QUOTE = 34,\n NEWLINE = 10,\n RETURN = 13;\n\nfunction objectConverter(columns) {\n return new Function(\"d\", \"return {\" + columns.map(function(name, i) {\n return JSON.stringify(name) + \": d[\" + i + \"]\";\n }).join(\",\") + \"}\");\n}\n\nfunction customConverter(columns, f) {\n var object = objectConverter(columns);\n return function(row, i) {\n return f(object(row), i, columns);\n };\n}\n\n// Compute unique columns in order of discovery.\nfunction inferColumns(rows) {\n var columnSet = Object.create(null),\n columns = [];\n\n rows.forEach(function(row) {\n for (var column in row) {\n if (!(column in columnSet)) {\n columns.push(columnSet[column] = column);\n }\n }\n });\n\n return columns;\n}\n\nfunction pad(value, width) {\n var s = value + \"\", length = s.length;\n return length < width ? new Array(width - length + 1).join(0) + s : s;\n}\n\nfunction formatYear(year) {\n return year < 0 ? \"-\" + pad(-year, 6)\n : year > 9999 ? \"+\" + pad(year, 6)\n : pad(year, 4);\n}\n\nfunction formatDate(date) {\n var hours = date.getUTCHours(),\n minutes = date.getUTCMinutes(),\n seconds = date.getUTCSeconds(),\n milliseconds = date.getUTCMilliseconds();\n return isNaN(date) ? \"Invalid Date\"\n : formatYear(date.getUTCFullYear(), 4) + \"-\" + pad(date.getUTCMonth() + 1, 2) + \"-\" + pad(date.getUTCDate(), 2)\n + (milliseconds ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \":\" + pad(seconds, 2) + \".\" + pad(milliseconds, 3) + \"Z\"\n : seconds ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \":\" + pad(seconds, 2) + \"Z\"\n : minutes || hours ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \"Z\"\n : \"\");\n}\n\nexport default function(delimiter) {\n var reFormat = new RegExp(\"[\\\"\" + delimiter + \"\\n\\r]\"),\n DELIMITER = delimiter.charCodeAt(0);\n\n function parse(text, f) {\n var convert, columns, rows = parseRows(text, function(row, i) {\n if (convert) return convert(row, i - 1);\n columns = row, convert = f ? customConverter(row, f) : objectConverter(row);\n });\n rows.columns = columns || [];\n return rows;\n }\n\n function parseRows(text, f) {\n var rows = [], // output rows\n N = text.length,\n I = 0, // current character index\n n = 0, // current line number\n t, // current token\n eof = N <= 0, // current token followed by EOF?\n eol = false; // current token followed by EOL?\n\n // Strip the trailing newline.\n if (text.charCodeAt(N - 1) === NEWLINE) --N;\n if (text.charCodeAt(N - 1) === RETURN) --N;\n\n function token() {\n if (eof) return EOF;\n if (eol) return eol = false, EOL;\n\n // Unescape quotes.\n var i, j = I, c;\n if (text.charCodeAt(j) === QUOTE) {\n while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE);\n if ((i = I) >= N) eof = true;\n else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true;\n else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; }\n return text.slice(j + 1, i - 1).replace(/\"\"/g, \"\\\"\");\n }\n\n // Find next delimiter or newline.\n while (I < N) {\n if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true;\n else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; }\n else if (c !== DELIMITER) continue;\n return text.slice(j, i);\n }\n\n // Return last token before EOF.\n return eof = true, text.slice(j, N);\n }\n\n while ((t = token()) !== EOF) {\n var row = [];\n while (t !== EOL && t !== EOF) row.push(t), t = token();\n if (f && (row = f(row, n++)) == null) continue;\n rows.push(row);\n }\n\n return rows;\n }\n\n function preformatBody(rows, columns) {\n return rows.map(function(row) {\n return columns.map(function(column) {\n return formatValue(row[column]);\n }).join(delimiter);\n });\n }\n\n function format(rows, columns) {\n if (columns == null) columns = inferColumns(rows);\n return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join(\"\\n\");\n }\n\n function formatBody(rows, columns) {\n if (columns == null) columns = inferColumns(rows);\n return preformatBody(rows, columns).join(\"\\n\");\n }\n\n function formatRows(rows) {\n return rows.map(formatRow).join(\"\\n\");\n }\n\n function formatRow(row) {\n return row.map(formatValue).join(delimiter);\n }\n\n function formatValue(value) {\n return value == null ? \"\"\n : value instanceof Date ? formatDate(value)\n : reFormat.test(value += \"\") ? \"\\\"\" + value.replace(/\"/g, \"\\\"\\\"\") + \"\\\"\"\n : value;\n }\n\n return {\n parse: parse,\n parseRows: parseRows,\n format: format,\n formatBody: formatBody,\n formatRows: formatRows\n };\n}\n","import dsv from \"./dsv\";\n\nvar csv = dsv(\",\");\n\nexport var csvParse = csv.parse;\nexport var csvParseRows = csv.parseRows;\nexport var csvFormat = csv.format;\nexport var csvFormatBody = csv.formatBody;\nexport var csvFormatRows = csv.formatRows;\n","import dsv from \"./dsv\";\n\nvar tsv = dsv(\"\\t\");\n\nexport var tsvParse = tsv.parse;\nexport var tsvParseRows = tsv.parseRows;\nexport var tsvFormat = tsv.format;\nexport var tsvFormatBody = tsv.formatBody;\nexport var tsvFormatRows = tsv.formatRows;\n","import { dsvFormat as d3Dsv } from 'd3-dsv';\nimport DSVArr from './dsv-arr';\n\n/**\n * Parses and converts data formatted in DSV string to a manageable internal format.\n *\n * @todo Support to be given for https://tools.ietf.org/html/rfc4180.\n * @todo Sample implementation https://github.com/knrz/CSV.js/.\n *\n * @param {string} str - The input DSV string.\n * @param {Object} options - Option to control the behaviour of the parsing.\n * @param {boolean} [options.firstRowHeader=true] - Whether the first row of the dsv string data is header or not.\n * @param {string} [options.fieldSeparator=\",\"] - The separator of two consecutive field.\n * @return {Array} Returns an array of headers and column major data.\n * @example\n *\n * // Sample input data:\n * const data = `\n * a,b,c\n * 1,2,3\n * 4,5,6\n * 7,8,9\n * `\n */\nfunction DSVStr (str, options) {\n const defaultOption = {\n firstRowHeader: true,\n fieldSeparator: ','\n };\n options = Object.assign({}, defaultOption, options);\n\n const dsv = d3Dsv(options.fieldSeparator);\n return DSVArr(dsv.parseRows(str), options);\n}\n\nexport default DSVStr;\n","import { columnMajor } from '../utils';\n\n/**\n * Parses and converts data formatted in JSON to a manageable internal format.\n *\n * @param {Array.} arr - The input data formatted in JSON.\n * @return {Array.} Returns an array of headers and column major data.\n * @example\n *\n * // Sample input data:\n * const data = [\n * {\n * \"a\": 1,\n * \"b\": 2,\n * \"c\": 3\n * },\n * {\n * \"a\": 4,\n * \"b\": 5,\n * \"c\": 6\n * },\n * {\n * \"a\": 7,\n * \"b\": 8,\n * \"c\": 9\n * }\n * ];\n */\nfunction FlatJSON (arr) {\n const header = {};\n let i = 0;\n let insertionIndex;\n const columns = [];\n const push = columnMajor(columns);\n\n arr.forEach((item) => {\n const fields = [];\n for (let key in item) {\n if (key in header) {\n insertionIndex = header[key];\n } else {\n header[key] = i++;\n insertionIndex = i - 1;\n }\n fields[insertionIndex] = item[key];\n }\n push(...fields);\n });\n\n return [Object.keys(header), columns];\n}\n\nexport default FlatJSON;\n","import FlatJSON from './flat-json';\nimport DSVArr from './dsv-arr';\nimport DSVStr from './dsv-str';\nimport { detectDataFormat } from '../utils';\n\n/**\n * Parses the input data and detect the format automatically.\n *\n * @param {string|Array} data - The input data.\n * @param {Object} options - An optional config specific to data format.\n * @return {Array.} Returns an array of headers and column major data.\n */\nfunction Auto (data, options) {\n const converters = { FlatJSON, DSVStr, DSVArr };\n const dataFormat = detectDataFormat(data);\n\n if (!dataFormat) {\n throw new Error('Couldn\\'t detect the data format');\n }\n\n return converters[dataFormat](data, options);\n}\n\nexport default Auto;\n","import { FieldType, FilteringMode, DimensionSubtype, MeasureSubtype, DataFormat } from './enums';\nimport fieldStore from './field-store';\nimport Value from './value';\nimport {\n rowDiffsetIterator\n} from './operator';\nimport { DM_DERIVATIVES, LOGICAL_OPERATORS } from './constants';\nimport { createFields, createUnitFieldFromPartial } from './field-creator';\nimport defaultConfig from './default-config';\nimport * as converter from './converter';\nimport { extend2, detectDataFormat } from './utils';\n\n/**\n * Prepares the selection data.\n */\nfunction prepareSelectionData (fields, i) {\n const resp = {};\n for (let field of fields) {\n resp[field.name()] = new Value(field.partialField.data[i], field);\n }\n return resp;\n}\n\nexport function prepareJoinData (fields) {\n const resp = {};\n Object.keys(fields).forEach((key) => { resp[key] = new Value(fields[key], key); });\n return resp;\n}\n\nexport const updateFields = ([rowDiffset, colIdentifier], partialFieldspace, fieldStoreName) => {\n let collID = colIdentifier.length ? colIdentifier.split(',') : [];\n let partialFieldMap = partialFieldspace.fieldsObj();\n let newFields = collID.map(coll => createUnitFieldFromPartial(partialFieldMap[coll].partialField, rowDiffset));\n return fieldStore.createNamespace(newFields, fieldStoreName);\n};\n\nexport const persistCurrentDerivation = (model, operation, config = {}, criteriaFn) => {\n if (operation === DM_DERIVATIVES.COMPOSE) {\n model._derivation.length = 0;\n model._derivation.push(...criteriaFn);\n } else {\n model._derivation.push({\n op: operation,\n meta: config,\n criteria: criteriaFn\n });\n }\n};\nexport const persistAncestorDerivation = (sourceDm, newDm) => {\n newDm._ancestorDerivation.push(...sourceDm._ancestorDerivation, ...sourceDm._derivation);\n};\n\nexport const persistDerivations = (sourceDm, model, operation, config = {}, criteriaFn) => {\n persistCurrentDerivation(model, operation, config, criteriaFn);\n persistAncestorDerivation(sourceDm, model);\n};\n\nconst selectModeMap = {\n [FilteringMode.NORMAL]: {\n diffIndex: ['rowDiffset'],\n calcDiff: [true, false]\n },\n [FilteringMode.INVERSE]: {\n diffIndex: ['rejectRowDiffset'],\n calcDiff: [false, true]\n },\n [FilteringMode.ALL]: {\n diffIndex: ['rowDiffset', 'rejectRowDiffset'],\n calcDiff: [true, true]\n }\n};\n\nconst generateRowDiffset = (rowDiffset, i, lastInsertedValue) => {\n if (lastInsertedValue !== -1 && i === (lastInsertedValue + 1)) {\n const li = rowDiffset.length - 1;\n\n rowDiffset[li] = `${rowDiffset[li].split('-')[0]}-${i}`;\n } else {\n rowDiffset.push(`${i}`);\n }\n};\n\nexport const selectRowDiffsetIterator = (rowDiffset, checker, mode) => {\n let lastInsertedValueSel = -1;\n let lastInsertedValueRej = -1;\n const newRowDiffSet = [];\n const rejRowDiffSet = [];\n\n const [shouldSelect, shouldReject] = selectModeMap[mode].calcDiff;\n\n rowDiffsetIterator(rowDiffset, (i) => {\n const checkerResult = checker(i);\n checkerResult && shouldSelect && generateRowDiffset(newRowDiffSet, i, lastInsertedValueSel);\n !checkerResult && shouldReject && generateRowDiffset(rejRowDiffSet, i, lastInsertedValueRej);\n });\n return {\n rowDiffset: newRowDiffSet.join(','),\n rejectRowDiffset: rejRowDiffSet.join(',')\n };\n};\n\n\nexport const rowSplitDiffsetIterator = (rowDiffset, checker, mode, dimensionArr, fieldStoreObj) => {\n let lastInsertedValue = {};\n const splitRowDiffset = {};\n const dimensionMap = {};\n\n rowDiffsetIterator(rowDiffset, (i) => {\n if (checker(i)) {\n let hash = '';\n\n let dimensionSet = { keys: {} };\n\n dimensionArr.forEach((_) => {\n const data = fieldStoreObj[_].partialField.data[i];\n hash = `${hash}-${data}`;\n dimensionSet.keys[_] = data;\n });\n\n if (splitRowDiffset[hash] === undefined) {\n splitRowDiffset[hash] = [];\n lastInsertedValue[hash] = -1;\n dimensionMap[hash] = dimensionSet;\n }\n\n generateRowDiffset(splitRowDiffset[hash], i, lastInsertedValue[hash]);\n lastInsertedValue[hash] = i;\n }\n });\n\n return {\n splitRowDiffset,\n dimensionMap\n };\n};\n\n\nexport const selectHelper = (clonedDm, selectFn, config, sourceDm, iterator) => {\n let cachedStore = {};\n let cloneProvider = () => sourceDm.detachedRoot();\n const { mode } = config;\n const rowDiffset = clonedDm._rowDiffset;\n const fields = clonedDm.getPartialFieldspace().fields;\n const selectorHelperFn = index => selectFn(\n prepareSelectionData(fields, index),\n index,\n cloneProvider,\n cachedStore\n );\n\n return iterator(rowDiffset, selectorHelperFn, mode);\n};\n\nexport const cloneWithAllFields = (model) => {\n const clonedDm = model.clone(false);\n const partialFieldspace = model.getPartialFieldspace();\n clonedDm._colIdentifier = partialFieldspace.fields.map(f => f.name()).join(',');\n\n // flush out cached namespace values on addition of new fields\n partialFieldspace._cachedFieldsObj = null;\n partialFieldspace._cachedDimension = null;\n partialFieldspace._cachedMeasure = null;\n clonedDm.__calculateFieldspace().calculateFieldsConfig();\n\n return clonedDm;\n};\n\nconst getKey = (arr, data, fn) => {\n let key = fn(arr, data, 0);\n\n for (let i = 1, len = arr.length; i < len; i++) {\n key = `${key},${fn(arr, data, i)}`;\n }\n return key;\n};\n\nexport const filterPropagationModel = (model, propModels, config = {}) => {\n let fns = [];\n const operation = config.operation || LOGICAL_OPERATORS.AND;\n const filterByMeasure = config.filterByMeasure || false;\n const clonedModel = cloneWithAllFields(model);\n const modelFieldsConfig = clonedModel.getFieldsConfig();\n\n if (!propModels.length) {\n fns = [() => false];\n } else {\n fns = propModels.map(propModel => ((dataModel) => {\n let keyFn;\n const dataObj = dataModel.getData();\n const fieldsConfig = dataModel.getFieldsConfig();\n const dimensions = Object.keys(dataModel.getFieldspace().getDimension())\n .filter(d => d in modelFieldsConfig);\n const dLen = dimensions.length;\n const indices = dimensions.map(d =>\n fieldsConfig[d].index);\n const measures = Object.keys(dataModel.getFieldspace().getMeasure())\n .filter(d => d in modelFieldsConfig);\n const fieldsSpace = dataModel.getFieldspace().fieldsObj();\n const data = dataObj.data;\n const domain = measures.reduce((acc, v) => {\n acc[v] = fieldsSpace[v].domain();\n return acc;\n }, {});\n const valuesMap = {};\n\n keyFn = (arr, row, idx) => row[arr[idx]];\n if (dLen) {\n data.forEach((row) => {\n const key = getKey(indices, row, keyFn);\n valuesMap[key] = 1;\n });\n }\n\n keyFn = (arr, fields, idx) => fields[arr[idx]].value;\n return data.length ? (fields) => {\n const present = dLen ? valuesMap[getKey(dimensions, fields, keyFn)] : true;\n\n if (filterByMeasure) {\n return measures.every(field => fields[field].value >= domain[field][0] &&\n fields[field].value <= domain[field][1]) && present;\n }\n return present;\n } : () => false;\n })(propModel));\n }\n\n let filteredModel;\n if (operation === LOGICAL_OPERATORS.AND) {\n filteredModel = clonedModel.select(fields => fns.every(fn => fn(fields)), {\n saveChild: false\n });\n } else {\n filteredModel = clonedModel.select(fields => fns.some(fn => fn(fields)), {\n saveChild: false\n });\n }\n\n return filteredModel;\n};\n\n\nexport const splitWithSelect = (sourceDm, dimensionArr, reducerFn = val => val, config) => {\n const {\n saveChild,\n } = config;\n const fieldStoreObj = sourceDm.getFieldspace().fieldsObj();\n\n const {\n splitRowDiffset,\n dimensionMap\n } = selectHelper(\n sourceDm.clone(saveChild),\n reducerFn,\n config,\n sourceDm,\n (...params) => rowSplitDiffsetIterator(...params, dimensionArr, fieldStoreObj)\n );\n\n const clonedDMs = [];\n Object.keys(splitRowDiffset).sort().forEach((e) => {\n if (splitRowDiffset[e]) {\n const cloned = sourceDm.clone(saveChild);\n const derivation = dimensionMap[e];\n cloned._rowDiffset = splitRowDiffset[e].join(',');\n cloned.__calculateFieldspace().calculateFieldsConfig();\n\n const derivationFormula = fields => dimensionArr.every(_ => fields[_].value === derivation.keys[_]);\n // Store reference to child model and selector function\n if (saveChild) {\n persistDerivations(sourceDm, cloned, DM_DERIVATIVES.SELECT, config, derivationFormula);\n }\n cloned._derivation[cloned._derivation.length - 1].meta = dimensionMap[e];\n\n clonedDMs.push(cloned);\n }\n });\n\n\n return clonedDMs;\n};\nexport const addDiffsetToClonedDm = (clonedDm, rowDiffset, sourceDm, selectConfig, selectFn) => {\n clonedDm._rowDiffset = rowDiffset;\n clonedDm.__calculateFieldspace().calculateFieldsConfig();\n persistDerivations(\n sourceDm,\n clonedDm,\n DM_DERIVATIVES.SELECT,\n { config: selectConfig },\n selectFn\n );\n};\n\n\nexport const cloneWithSelect = (sourceDm, selectFn, selectConfig, cloneConfig) => {\n let extraCloneDm = {};\n\n let { mode } = selectConfig;\n\n const cloned = sourceDm.clone(cloneConfig.saveChild);\n const setOfRowDiffsets = selectHelper(\n cloned,\n selectFn,\n selectConfig,\n sourceDm,\n selectRowDiffsetIterator\n );\n const diffIndex = selectModeMap[mode].diffIndex;\n\n addDiffsetToClonedDm(cloned, setOfRowDiffsets[diffIndex[0]], sourceDm, selectConfig, selectFn);\n\n if (diffIndex.length > 1) {\n extraCloneDm = sourceDm.clone(cloneConfig.saveChild);\n addDiffsetToClonedDm(extraCloneDm, setOfRowDiffsets[diffIndex[1]], sourceDm, selectConfig, selectFn);\n return [cloned, extraCloneDm];\n }\n\n return cloned;\n};\n\nexport const cloneWithProject = (sourceDm, projField, config, allFields) => {\n const cloned = sourceDm.clone(config.saveChild);\n let projectionSet = projField;\n if (config.mode === FilteringMode.INVERSE) {\n projectionSet = allFields.filter(fieldName => projField.indexOf(fieldName) === -1);\n }\n // cloned._colIdentifier = sourceDm._colIdentifier.split(',')\n // .filter(coll => projectionSet.indexOf(coll) !== -1).join();\n cloned._colIdentifier = projectionSet.join(',');\n cloned.__calculateFieldspace().calculateFieldsConfig();\n\n persistDerivations(\n sourceDm,\n cloned,\n DM_DERIVATIVES.PROJECT,\n { projField, config, actualProjField: projectionSet },\n null\n );\n\n return cloned;\n};\n\n\nexport const splitWithProject = (sourceDm, projFieldSet, config, allFields) =>\n projFieldSet.map(projFields =>\n cloneWithProject(sourceDm, projFields, config, allFields));\n\nexport const sanitizeUnitSchema = (unitSchema) => {\n // Do deep clone of the unit schema as the user might change it later.\n unitSchema = extend2({}, unitSchema);\n if (!unitSchema.type) {\n unitSchema.type = FieldType.DIMENSION;\n }\n\n if (!unitSchema.subtype) {\n switch (unitSchema.type) {\n case FieldType.MEASURE:\n unitSchema.subtype = MeasureSubtype.CONTINUOUS;\n break;\n default:\n case FieldType.DIMENSION:\n unitSchema.subtype = DimensionSubtype.CATEGORICAL;\n break;\n }\n }\n\n return unitSchema;\n};\n\nexport const validateUnitSchema = (unitSchema) => {\n const supportedMeasureSubTypes = [MeasureSubtype.CONTINUOUS];\n const supportedDimSubTypes = [\n DimensionSubtype.CATEGORICAL,\n DimensionSubtype.BINNED,\n DimensionSubtype.TEMPORAL,\n DimensionSubtype.GEO\n ];\n const { type, subtype, name } = unitSchema;\n\n switch (type) {\n case FieldType.DIMENSION:\n if (supportedDimSubTypes.indexOf(subtype) === -1) {\n throw new Error(`DataModel doesn't support dimension field subtype ${subtype} used for ${name} field`);\n }\n break;\n case FieldType.MEASURE:\n if (supportedMeasureSubTypes.indexOf(subtype) === -1) {\n throw new Error(`DataModel doesn't support measure field subtype ${subtype} used for ${name} field`);\n }\n break;\n default:\n throw new Error(`DataModel doesn't support field type ${type} used for ${name} field`);\n }\n};\n\nexport const sanitizeAndValidateSchema = schema => schema.map((unitSchema) => {\n unitSchema = sanitizeUnitSchema(unitSchema);\n validateUnitSchema(unitSchema);\n return unitSchema;\n});\n\nexport const resolveFieldName = (schema, dataHeader) => {\n schema.forEach((unitSchema) => {\n const fieldNameAs = unitSchema.as;\n if (!fieldNameAs) { return; }\n\n const idx = dataHeader.indexOf(unitSchema.name);\n dataHeader[idx] = fieldNameAs;\n unitSchema.name = fieldNameAs;\n delete unitSchema.as;\n });\n};\n\nexport const updateData = (relation, data, schema, options) => {\n schema = sanitizeAndValidateSchema(schema);\n options = Object.assign(Object.assign({}, defaultConfig), options);\n const converterFn = converter[options.dataFormat];\n\n if (!(converterFn && typeof converterFn === 'function')) {\n throw new Error(`No converter function found for ${options.dataFormat} format`);\n }\n\n const [header, formattedData] = converterFn(data, options);\n resolveFieldName(schema, header);\n const fieldArr = createFields(formattedData, schema, header);\n\n // This will create a new fieldStore with the fields\n const nameSpace = fieldStore.createNamespace(fieldArr, options.name);\n relation._partialFieldspace = nameSpace;\n\n // If data is provided create the default colIdentifier and rowDiffset\n relation._rowDiffset = formattedData.length && formattedData[0].length ? `0-${formattedData[0].length - 1}` : '';\n\n // This stores the value objects which is passed to the filter method when selection operation is done.\n const valueObjects = [];\n rowDiffsetIterator(relation._rowDiffset, (i) => {\n valueObjects[i] = prepareSelectionData(nameSpace.fields, i);\n });\n nameSpace._cachedValueObjects = valueObjects;\n\n relation._colIdentifier = (schema.map(_ => _.name)).join();\n relation._dataFormat = options.dataFormat === DataFormat.AUTO ? detectDataFormat(data) : options.dataFormat;\n return relation;\n};\n\nexport const fieldInSchema = (schema, field) => {\n let i = 0;\n\n for (; i < schema.length; ++i) {\n if (field === schema[i].name) {\n return {\n type: schema[i].subtype || schema[i].type,\n index: i\n };\n }\n }\n return null;\n};\n\n\nexport const getDerivationArguments = (derivation) => {\n let params = [];\n let operation;\n operation = derivation.op;\n switch (operation) {\n case DM_DERIVATIVES.SELECT:\n params = [derivation.criteria];\n break;\n case DM_DERIVATIVES.PROJECT:\n params = [derivation.meta.actualProjField];\n break;\n case DM_DERIVATIVES.GROUPBY:\n operation = 'groupBy';\n params = [derivation.meta.groupByString.split(','), derivation.criteria];\n break;\n default:\n operation = null;\n }\n\n return {\n operation,\n params\n };\n};\n\nconst applyExistingOperationOnModel = (propModel, dataModel) => {\n const derivations = dataModel.getDerivations();\n let selectionModel = propModel;\n\n derivations.forEach((derivation) => {\n if (!derivation) {\n return;\n }\n\n const { operation, params } = getDerivationArguments(derivation);\n if (operation) {\n selectionModel = selectionModel[operation](...params, {\n saveChild: false\n });\n }\n });\n\n return selectionModel;\n};\n\nconst getFilteredModel = (propModel, path) => {\n for (let i = 0, len = path.length; i < len; i++) {\n const model = path[i];\n propModel = applyExistingOperationOnModel(propModel, model);\n }\n return propModel;\n};\n\nconst propagateIdentifiers = (dataModel, propModel, config = {}, propModelInf = {}) => {\n const nonTraversingModel = propModelInf.nonTraversingModel;\n const excludeModels = propModelInf.excludeModels || [];\n\n if (dataModel === nonTraversingModel) {\n return;\n }\n\n const propagate = excludeModels.length ? excludeModels.indexOf(dataModel) === -1 : true;\n\n propagate && dataModel.handlePropagation(propModel, config);\n\n const children = dataModel._children;\n children.forEach((child) => {\n const selectionModel = applyExistingOperationOnModel(propModel, child);\n propagateIdentifiers(child, selectionModel, config, propModelInf);\n });\n};\n\nexport const getRootGroupByModel = (model) => {\n while (model._parent && model._derivation.find(d => d.op !== DM_DERIVATIVES.GROUPBY)) {\n model = model._parent;\n }\n return model;\n};\n\nexport const getRootDataModel = (model) => {\n while (model._parent) {\n model = model._parent;\n }\n return model;\n};\n\nexport const getPathToRootModel = (model, path = []) => {\n while (model._parent) {\n path.push(model);\n model = model._parent;\n }\n return path;\n};\n\nexport const propagateToAllDataModels = (identifiers, rootModels, propagationInf, config) => {\n let criteria;\n let propModel;\n const { propagationNameSpace, propagateToSource } = propagationInf;\n const propagationSourceId = propagationInf.sourceId;\n const propagateInterpolatedValues = config.propagateInterpolatedValues;\n const filterFn = (entry) => {\n const filter = config.filterFn || (() => true);\n return filter(entry, config);\n };\n\n let criterias = [];\n\n if (identifiers === null && config.persistent !== true) {\n criterias = [{\n criteria: []\n }];\n criteria = [];\n } else {\n let actionCriterias = Object.values(propagationNameSpace.mutableActions);\n if (propagateToSource !== false) {\n actionCriterias = actionCriterias.filter(d => d.config.sourceId !== propagationSourceId);\n }\n\n const filteredCriteria = actionCriterias.filter(filterFn).map(action => action.config.criteria);\n\n const excludeModels = [];\n\n if (propagateToSource !== false) {\n const sourceActionCriterias = Object.values(propagationNameSpace.mutableActions);\n\n sourceActionCriterias.forEach((actionInf) => {\n const actionConf = actionInf.config;\n if (actionConf.applyOnSource === false && actionConf.action === config.action &&\n actionConf.sourceId !== propagationSourceId) {\n excludeModels.push(actionInf.model);\n criteria = sourceActionCriterias.filter(d => d !== actionInf).map(d => d.config.criteria);\n criteria.length && criterias.push({\n criteria,\n models: actionInf.model,\n path: getPathToRootModel(actionInf.model)\n });\n }\n });\n }\n\n\n criteria = [].concat(...[...filteredCriteria, identifiers]).filter(d => d !== null);\n criterias.push({\n criteria,\n excludeModels: [...excludeModels, ...config.excludeModels || []]\n });\n }\n\n const rootModel = rootModels.model;\n\n const propConfig = Object.assign({\n sourceIdentifiers: identifiers,\n propagationSourceId\n }, config);\n\n const rootGroupByModel = rootModels.groupByModel;\n if (propagateInterpolatedValues && rootGroupByModel) {\n propModel = filterPropagationModel(rootGroupByModel, criteria, {\n filterByMeasure: propagateInterpolatedValues\n });\n propagateIdentifiers(rootGroupByModel, propModel, propConfig);\n }\n\n criterias.forEach((inf) => {\n const propagationModel = filterPropagationModel(rootModel, inf.criteria);\n const path = inf.path;\n\n if (path) {\n const filteredModel = getFilteredModel(propagationModel, path.reverse());\n inf.models.handlePropagation(filteredModel, propConfig);\n } else {\n propagateIdentifiers(rootModel, propagationModel, propConfig, {\n excludeModels: inf.excludeModels,\n nonTraversingModel: propagateInterpolatedValues && rootGroupByModel\n });\n }\n });\n};\n\nexport const propagateImmutableActions = (propagationNameSpace, rootModels, propagationInf) => {\n const immutableActions = propagationNameSpace.immutableActions;\n\n for (const action in immutableActions) {\n const actionInf = immutableActions[action];\n const actionConf = actionInf.config;\n const propagationSourceId = propagationInf.config.sourceId;\n const filterImmutableAction = propagationInf.propConfig.filterImmutableAction ?\n propagationInf.propConfig.filterImmutableAction(actionConf, propagationInf.config) : true;\n if (actionConf.sourceId !== propagationSourceId && filterImmutableAction) {\n const criteriaModel = actionConf.criteria;\n propagateToAllDataModels(criteriaModel, rootModels, {\n propagationNameSpace,\n propagateToSource: false,\n sourceId: propagationSourceId\n }, actionConf);\n }\n }\n};\n\nexport const addToPropNamespace = (propagationNameSpace, config = {}, model) => {\n let sourceNamespace;\n const isMutableAction = config.isMutableAction;\n const criteria = config.criteria;\n const key = `${config.action}-${config.sourceId}`;\n\n if (isMutableAction) {\n sourceNamespace = propagationNameSpace.mutableActions;\n } else {\n sourceNamespace = propagationNameSpace.immutableActions;\n }\n\n if (criteria === null) {\n delete sourceNamespace[key];\n } else {\n sourceNamespace[key] = {\n model,\n config\n };\n }\n\n return this;\n};\n\n\nexport const getNormalizedProFields = (projField, allFields, fieldConfig) => {\n const normalizedProjField = projField.reduce((acc, field) => {\n if (field.constructor.name === 'RegExp') {\n acc.push(...allFields.filter(fieldName => fieldName.search(field) !== -1));\n } else if (field in fieldConfig) {\n acc.push(field);\n }\n return acc;\n }, []);\n return Array.from(new Set(normalizedProjField)).map(field => field.trim());\n};\n","import { FilteringMode } from './enums';\nimport { getUniqueId } from './utils';\nimport {\n updateFields,\n cloneWithSelect,\n cloneWithProject,\n updateData,\n getNormalizedProFields\n} from './helper';\nimport { crossProduct, difference, naturalJoinFilter, union } from './operator';\n\n/**\n * Relation provides the definitions of basic operators of relational algebra like *selection*, *projection*, *union*,\n * *difference* etc.\n *\n * It is extended by {@link DataModel} to inherit the functionalities of relational algebra concept.\n *\n * @class\n * @public\n * @module Relation\n * @namespace DataModel\n */\nclass Relation {\n\n /**\n * Creates a new Relation instance by providing underlying data and schema.\n *\n * @private\n *\n * @param {Object | string | Relation} data - The input tabular data in dsv or json format or\n * an existing Relation instance object.\n * @param {Array} schema - An array of data schema.\n * @param {Object} [options] - The optional options.\n */\n constructor (...params) {\n let source;\n\n this._parent = null;\n this._derivation = [];\n this._ancestorDerivation = [];\n this._children = [];\n\n if (params.length === 1 && ((source = params[0]) instanceof Relation)) {\n // parent datamodel was passed as part of source\n this._colIdentifier = source._colIdentifier;\n this._rowDiffset = source._rowDiffset;\n this._dataFormat = source._dataFormat;\n this._parent = source;\n this._partialFieldspace = this._parent._partialFieldspace;\n this._fieldStoreName = getUniqueId();\n this.__calculateFieldspace().calculateFieldsConfig();\n } else {\n updateData(this, ...params);\n this._fieldStoreName = this._partialFieldspace.name;\n this.__calculateFieldspace().calculateFieldsConfig();\n this._propagationNameSpace = {\n mutableActions: {},\n immutableActions: {}\n };\n }\n }\n\n /**\n * Retrieves the {@link Schema | schema} details for every {@link Field | field} as an array.\n *\n * @public\n *\n * @return {Array.} Array of fields schema.\n * ```\n * [\n * { name: 'Name', type: 'dimension' },\n * { name: 'Miles_per_Gallon', type: 'measure', numberFormat: (val) => `${val} miles / gallon` },\n * { name: 'Cylinder', type: 'dimension' },\n * { name: 'Displacement', type: 'measure', defAggFn: 'max' },\n * { name: 'HorsePower', type: 'measure', defAggFn: 'max' },\n * { name: 'Weight_in_lbs', type: 'measure', defAggFn: 'avg', },\n * { name: 'Acceleration', type: 'measure', defAggFn: 'avg' },\n * { name: 'Year', type: 'dimension', subtype: 'datetime', format: '%Y' },\n * { name: 'Origin' }\n * ]\n * ```\n */\n getSchema () {\n return this.getFieldspace().fields.map(d => d.schema());\n }\n\n /**\n * Returns the name of the {@link DataModel} instance. If no name was specified during {@link DataModel}\n * initialization, then it returns a auto-generated name.\n *\n * @public\n *\n * @return {string} Name of the DataModel instance.\n */\n getName() {\n return this._fieldStoreName;\n }\n\n getFieldspace () {\n return this._fieldspace;\n }\n\n __calculateFieldspace () {\n this._fieldspace = updateFields([this._rowDiffset, this._colIdentifier],\n this.getPartialFieldspace(), this._fieldStoreName);\n return this;\n }\n\n getPartialFieldspace () {\n return this._partialFieldspace;\n }\n\n /**\n * Performs {@link link_of_cross_product | cross-product} between two {@link DataModel} instances and returns a\n * new {@link DataModel} instance containing the results. This operation is also called theta join.\n *\n * Cross product takes two set and create one set where each value of one set is paired with each value of another\n * set.\n *\n * This method takes an optional predicate which filters the generated result rows. If the predicate returns true\n * the combined row is included in the resulatant table.\n *\n * @example\n * let originDM = dm.project(['Origin','Origin_Formal_Name']);\n * let carsDM = dm.project(['Name','Miles_per_Gallon','Origin'])\n *\n * console.log(carsDM.join(originDM)));\n *\n * console.log(carsDM.join(originDM,\n * obj => obj.[originDM.getName()].Origin === obj.[carsDM.getName()].Origin));\n *\n * @text\n * This is chained version of `join` operator. `join` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {DataModel} joinWith - The DataModel to be joined with the current instance DataModel.\n * @param {SelectionPredicate} filterFn - The predicate function that will filter the result of the crossProduct.\n *\n * @return {DataModel} New DataModel instance created after joining.\n */\n join (joinWith, filterFn) {\n return crossProduct(this, joinWith, filterFn);\n }\n\n /**\n * {@link natural_join | Natural join} is a special kind of cross-product join where filtering of rows are performed\n * internally by resolving common fields are from both table and the rows with common value are included.\n *\n * @example\n * let originDM = dm.project(['Origin','Origin_Formal_Name']);\n * let carsDM = dm.project(['Name','Miles_per_Gallon','Origin'])\n *\n * console.log(carsDM.naturalJoin(originDM));\n *\n * @text\n * This is chained version of `naturalJoin` operator. `naturalJoin` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {DataModel} joinWith - The DataModel with which the current instance of DataModel on which the method is\n * called will be joined.\n * @return {DataModel} New DataModel instance created after joining.\n */\n naturalJoin (joinWith) {\n return crossProduct(this, joinWith, naturalJoinFilter(this, joinWith), true);\n }\n\n /**\n * {@link link_to_union | Union} operation can be termed as vertical stacking of all rows from both the DataModel\n * instances, provided that both of the {@link DataModel} instances should have same column names.\n *\n * @example\n * console.log(EuropeanMakerDM.union(USAMakerDM));\n *\n * @text\n * This is chained version of `naturalJoin` operator. `naturalJoin` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {DataModel} unionWith - DataModel instance for which union has to be applied with the instance on which\n * the method is called\n *\n * @return {DataModel} New DataModel instance with the result of the operation\n */\n union (unionWith) {\n return union(this, unionWith);\n }\n\n /**\n * {@link link_to_difference | Difference } operation only include rows which are present in the datamodel on which\n * it was called but not on the one passed as argument.\n *\n * @example\n * console.log(highPowerDM.difference(highExpensiveDM));\n *\n * @text\n * This is chained version of `naturalJoin` operator. `naturalJoin` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {DataModel} differenceWith - DataModel instance for which difference has to be applied with the instance\n * on which the method is called\n * @return {DataModel} New DataModel instance with the result of the operation\n */\n difference (differenceWith) {\n return difference(this, differenceWith);\n }\n\n /**\n * {@link link_to_selection | Selection} is a row filtering operation. It expects a predicate and an optional mode\n * which control which all rows should be included in the resultant DataModel instance.\n *\n * {@link SelectionPredicate} is a function which returns a boolean value. For selection operation the selection\n * function is called for each row of DataModel instance with the current row passed as argument.\n *\n * After executing {@link SelectionPredicate} the rows are labeled as either an entry of selection set or an entry\n * of rejection set.\n *\n * {@link FilteringMode} operates on the selection and rejection set to determine which one would reflect in the\n * resultant datamodel.\n *\n * @warning\n * Selection and rejection set is only a logical idea for concept explanation purpose.\n *\n * @example\n * // with selection mode NORMAL:\n * const normDt = dt.select(fields => fields.Origin.value === \"USA\")\n * console.log(normDt));\n *\n * // with selection mode INVERSE:\n * const inverDt = dt.select(fields => fields.Origin.value === \"USA\", { mode: DataModel.FilteringMode.INVERSE })\n * console.log(inverDt);\n *\n * // with selection mode ALL:\n * const dtArr = dt.select(fields => fields.Origin.value === \"USA\", { mode: DataModel.FilteringMode.ALL })\n * // print the selected parts\n * console.log(dtArr[0]);\n * // print the inverted parts\n * console.log(dtArr[1]);\n *\n * @text\n * This is chained version of `select` operator. `select` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {Function} selectFn - The predicate function which is called for each row with the current row.\n * ```\n * function (row, i, cloneProvider, store) { ... }\n * ```\n * @param {Object} config - The configuration object to control the inclusion exclusion of a row in resultant\n * DataModel instance.\n * @param {FilteringMode} [config.mode=FilteringMode.NORMAL] - The mode of the selection.\n * @return {DataModel} Returns the new DataModel instance(s) after operation.\n */\n select (selectFn, config) {\n const defConfig = {\n mode: FilteringMode.NORMAL,\n saveChild: true\n };\n config = Object.assign({}, defConfig, config);\n config.mode = config.mode || defConfig.mode;\n\n const cloneConfig = { saveChild: config.saveChild };\n return cloneWithSelect(\n this,\n selectFn,\n config,\n cloneConfig\n );\n }\n\n /**\n * Retrieves a boolean value if the current {@link DataModel} instance has data.\n *\n * @example\n * const schema = [\n * { name: 'CarName', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n * const data = [];\n *\n * const dt = new DataModel(data, schema);\n * console.log(dt.isEmpty());\n *\n * @public\n *\n * @return {Boolean} True if the datamodel has no data, otherwise false.\n */\n isEmpty () {\n return !this._rowDiffset.length || !this._colIdentifier.length;\n }\n\n /**\n * Creates a clone from the current DataModel instance with child parent relationship.\n *\n * @private\n * @param {boolean} [saveChild=true] - Whether the cloned instance would be recorded in the parent instance.\n * @return {DataModel} - Returns the newly cloned DataModel instance.\n */\n clone (saveChild = true) {\n const clonedDm = new this.constructor(this);\n if (saveChild) {\n clonedDm.setParent(this);\n } else {\n clonedDm.setParent(null);\n }\n return clonedDm;\n }\n\n /**\n * {@link Projection} is filter column (field) operation. It expects list of fields' name and either include those\n * or exclude those based on {@link FilteringMode} on the resultant variable.\n *\n * Projection expects array of fields name based on which it creates the selection and rejection set. All the field\n * whose name is present in array goes in selection set and rest of the fields goes in rejection set.\n *\n * {@link FilteringMode} operates on the selection and rejection set to determine which one would reflect in the\n * resulatant datamodel.\n *\n * @warning\n * Selection and rejection set is only a logical idea for concept explanation purpose.\n *\n * @example\n * const dm = new DataModel(data, schema);\n *\n * // with projection mode NORMAL:\n * const normDt = dt.project([\"Name\", \"HorsePower\"]);\n * console.log(normDt.getData());\n *\n * // with projection mode INVERSE:\n * const inverDt = dt.project([\"Name\", \"HorsePower\"], { mode: DataModel.FilteringMode.INVERSE })\n * console.log(inverDt.getData());\n *\n * // with selection mode ALL:\n * const dtArr = dt.project([\"Name\", \"HorsePower\"], { mode: DataModel.FilteringMode.ALL })\n * // print the normal parts\n * console.log(dtArr[0].getData());\n * // print the inverted parts\n * console.log(dtArr[1].getData());\n *\n * @text\n * This is chained version of `select` operator. `select` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {Array.} projField - An array of column names in string or regular expression.\n * @param {Object} [config] - An optional config to control the creation of new DataModel\n * @param {FilteringMode} [config.mode=FilteringMode.NORMAL] - Mode of the projection\n *\n * @return {DataModel} Returns the new DataModel instance after operation.\n */\n project (projField, config) {\n const defConfig = {\n mode: FilteringMode.NORMAL,\n saveChild: true\n };\n config = Object.assign({}, defConfig, config);\n const fieldConfig = this.getFieldsConfig();\n const allFields = Object.keys(fieldConfig);\n const { mode } = config;\n const normalizedProjField = getNormalizedProFields(projField, allFields, fieldConfig);\n\n let dataModel;\n\n if (mode === FilteringMode.ALL) {\n let projectionClone = cloneWithProject(this, normalizedProjField, {\n mode: FilteringMode.NORMAL,\n saveChild: config.saveChild\n }, allFields);\n let rejectionClone = cloneWithProject(this, normalizedProjField, {\n mode: FilteringMode.INVERSE,\n saveChild: config.saveChild\n }, allFields);\n dataModel = [projectionClone, rejectionClone];\n } else {\n let projectionClone = cloneWithProject(this, normalizedProjField, config, allFields);\n dataModel = projectionClone;\n }\n\n return dataModel;\n }\n\n getFieldsConfig () {\n return this._fieldConfig;\n }\n\n calculateFieldsConfig () {\n this._fieldConfig = this._fieldspace.fields.reduce((acc, fieldObj, i) => {\n acc[fieldObj.name()] = {\n index: i,\n def: fieldObj.schema(),\n };\n return acc;\n }, {});\n return this;\n }\n\n\n /**\n * Frees up the resources associated with the current DataModel instance and breaks all the links instance has in\n * the DAG.\n *\n * @public\n */\n dispose () {\n this._parent && this._parent.removeChild(this);\n this._parent = null;\n this._children.forEach((child) => {\n child._parent = null;\n });\n this._children = [];\n }\n\n /**\n * Removes the specified child {@link DataModel} from the child list of the current {@link DataModel} instance.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n *\n * const dt2 = dt.select(fields => fields.Origin.value === \"USA\")\n * dt.removeChild(dt2);\n *\n * @private\n *\n * @param {DataModel} child - Delegates the parent to remove this child.\n */\n removeChild (child) {\n let idx = this._children.findIndex(sibling => sibling === child);\n idx !== -1 ? this._children.splice(idx, 1) : true;\n }\n\n /**\n * Sets the specified {@link DataModel} as a parent for the current {@link DataModel} instance.\n *\n * @param {DataModel} parent - The datamodel instance which will act as parent.\n */\n setParent (parent) {\n this._parent && this._parent.removeChild(this);\n this._parent = parent;\n parent && parent._children.push(this);\n }\n\n /**\n * Returns the parent {@link DataModel} instance.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n *\n * const dt2 = dt.select(fields => fields.Origin.value === \"USA\");\n * const parentDm = dt2.getParent();\n *\n * @return {DataModel} Returns the parent DataModel instance.\n */\n getParent () {\n return this._parent;\n }\n\n /**\n * Returns the immediate child {@link DataModel} instances.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n *\n * const childDm1 = dt.select(fields => fields.Origin.value === \"USA\");\n * const childDm2 = dt.select(fields => fields.Origin.value === \"Japan\");\n * const childDm3 = dt.groupBy([\"Origin\"]);\n *\n * @return {DataModel[]} Returns the immediate child DataModel instances.\n */\n getChildren () {\n return this._children;\n }\n\n /**\n * Returns the in-between operation meta data while creating the current {@link DataModel} instance.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n * const dt2 = dt.select(fields => fields.Origin.value === \"USA\");\n * const dt3 = dt2.groupBy([\"Origin\"]);\n * const derivations = dt3.getDerivations();\n *\n * @return {Any[]} Returns the derivation meta data.\n */\n getDerivations () {\n return this._derivation;\n }\n\n /**\n * Returns the in-between operation meta data happened from root {@link DataModel} to current instance.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n * const dt2 = dt.select(fields => fields.Origin.value === \"USA\");\n * const dt3 = dt2.groupBy([\"Origin\"]);\n * const ancDerivations = dt3.getAncestorDerivations();\n *\n * @return {Any[]} Returns the previous derivation meta data.\n */\n getAncestorDerivations () {\n return this._ancestorDerivation;\n }\n}\n\nexport default Relation;\n","/* eslint-disable default-case */\n\nimport { FieldType, DimensionSubtype, DataFormat, FilteringMode } from './enums';\nimport {\n persistDerivations,\n getRootGroupByModel,\n propagateToAllDataModels,\n getRootDataModel,\n propagateImmutableActions,\n addToPropNamespace,\n sanitizeUnitSchema,\n splitWithSelect,\n splitWithProject,\n getNormalizedProFields\n} from './helper';\nimport { DM_DERIVATIVES, PROPAGATION } from './constants';\nimport {\n dataBuilder,\n rowDiffsetIterator,\n groupBy\n} from './operator';\nimport { createBinnedFieldData } from './operator/bucket-creator';\nimport Relation from './relation';\nimport reducerStore from './utils/reducer-store';\nimport { createFields } from './field-creator';\nimport InvalidAwareTypes from './invalid-aware-types';\nimport Value from './value';\n\n/**\n * DataModel is an in-browser representation of tabular data. It supports\n * {@link https://en.wikipedia.org/wiki/Relational_algebra | relational algebra} operators as well as generic data\n * processing opearators.\n * DataModel extends {@link Relation} class which defines all the relational algebra opreators. DataModel gives\n * definition of generic data processing operators which are not relational algebra complient.\n *\n * @public\n * @class\n * @extends Relation\n * @memberof Datamodel\n */\nclass DataModel extends Relation {\n /**\n * Creates a new DataModel instance by providing data and schema. Data could be in the form of\n * - Flat JSON\n * - DSV String\n * - 2D Array\n *\n * By default DataModel finds suitable adapter to serialize the data. DataModel also expects a\n * {@link Schema | schema} for identifying the variables present in data.\n *\n * @constructor\n * @example\n * const data = loadData('cars.csv');\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'Miles_per_Gallon', type: 'measure', unit : 'cm', scale: '1000', numberformat: val => `${val}G`},\n * { name: 'Cylinders', type: 'dimension' },\n * { name: 'Displacement', type: 'measure' },\n * { name: 'Horsepower', type: 'measure' },\n * { name: 'Weight_in_lbs', type: 'measure' },\n * { name: 'Acceleration', type: 'measure' },\n * { name: 'Year', type: 'dimension', subtype: 'datetime', format: '%Y' },\n * { name: 'Origin', type: 'dimension' }\n * ];\n * const dm = new DataModel(data, schema, { name: 'Cars' });\n * table(dm);\n *\n * @public\n *\n * @param {Array. | string | Array.} data Input data in any of the mentioned formats\n * @param {Array.} schema Defination of the variables. Order of the variables in data and order of the\n * variables in schema has to be same.\n * @param {object} [options] Optional arguments to specify more settings regarding the creation part\n * @param {string} [options.name] Name of the datamodel instance. If no name is given an auto generated name is\n * assigned to the instance.\n * @param {string} [options.fieldSeparator=','] specify field separator type if the data is of type dsv string.\n */\n constructor (...args) {\n super(...args);\n\n this._onPropagation = [];\n }\n\n /**\n * Reducers are simple functions which reduces an array of numbers to a representative number of the set.\n * Like an array of numbers `[10, 20, 5, 15]` can be reduced to `12.5` if average / mean reducer function is\n * applied. All the measure fields in datamodel (variables in data) needs a reducer to handle aggregation.\n *\n * @public\n *\n * @return {ReducerStore} Singleton instance of {@link ReducerStore}.\n */\n static get Reducers () {\n return reducerStore;\n }\n\n /**\n * Configure null, undefined, invalid values in the source data\n *\n * @public\n *\n * @param {Object} [config] - Configuration to control how null, undefined and non-parsable values are\n * represented in DataModel.\n * @param {string} [config.undefined] - Define how an undefined value will be represented.\n * @param {string} [config.null] - Define how a null value will be represented.\n * @param {string} [config.invalid] - Define how a non-parsable value will be represented.\n */\n static configureInvalidAwareTypes (config) {\n return InvalidAwareTypes.invalidAwareVals(config);\n }\n\n /**\n * Retrieve the data attached to an instance in JSON format.\n *\n * @example\n * // DataModel instance is already prepared and assigned to dm variable\n * const data = dm.getData({\n * order: 'column',\n * formatter: {\n * origin: (val) => val === 'European Union' ? 'EU' : val;\n * }\n * });\n * console.log(data);\n *\n * @public\n *\n * @param {Object} [options] Options to control how the raw data is to be returned.\n * @param {string} [options.order='row'] Defines if data is retieved in row order or column order. Possible values\n * are `'rows'` and `'columns'`\n * @param {Function} [options.formatter=null] Formats the output data. This expects an object, where the keys are\n * the name of the variable needs to be formatted. The formatter function is called for each row passing the\n * value of the cell for a particular row as arguments. The formatter is a function in the form of\n * `function (value, rowId, schema) => { ... }`\n * Know more about {@link Fomatter}.\n *\n * @return {Array} Returns a multidimensional array of the data with schema. The return format looks like\n * ```\n * {\n * data,\n * schema\n * }\n * ```\n */\n getData (options) {\n const defOptions = {\n order: 'row',\n formatter: null,\n withUid: false,\n getAllFields: false,\n sort: []\n };\n options = Object.assign({}, defOptions, options);\n const fields = this.getPartialFieldspace().fields;\n\n const dataGenerated = dataBuilder.call(\n this,\n this.getPartialFieldspace().fields,\n this._rowDiffset,\n options.getAllFields ? fields.map(d => d.name()).join() : this._colIdentifier,\n options.sort,\n {\n columnWise: options.order === 'column',\n addUid: !!options.withUid\n }\n );\n\n if (!options.formatter) {\n return dataGenerated;\n }\n\n const { formatter } = options;\n const { data, schema, uids } = dataGenerated;\n const fieldNames = schema.map((e => e.name));\n const fmtFieldNames = Object.keys(formatter);\n const fmtFieldIdx = fmtFieldNames.reduce((acc, next) => {\n const idx = fieldNames.indexOf(next);\n if (idx !== -1) {\n acc.push([idx, formatter[next]]);\n }\n return acc;\n }, []);\n\n if (options.order === 'column') {\n fmtFieldIdx.forEach((elem) => {\n const fIdx = elem[0];\n const fmtFn = elem[1];\n\n data[fIdx].forEach((datum, datumIdx) => {\n data[fIdx][datumIdx] = fmtFn.call(\n undefined,\n datum,\n uids[datumIdx],\n schema[fIdx]\n );\n });\n });\n } else {\n data.forEach((datum, datumIdx) => {\n fmtFieldIdx.forEach((elem) => {\n const fIdx = elem[0];\n const fmtFn = elem[1];\n\n datum[fIdx] = fmtFn.call(\n undefined,\n datum[fIdx],\n uids[datumIdx],\n schema[fIdx]\n );\n });\n });\n }\n\n return dataGenerated;\n }\n\n /**\n * Returns the unique ids in an array.\n *\n * @return {Array} Returns an array of ids.\n */\n getUids () {\n const rowDiffset = this._rowDiffset;\n const ids = [];\n\n if (rowDiffset.length) {\n const diffSets = rowDiffset.split(',');\n\n diffSets.forEach((set) => {\n let [start, end] = set.split('-').map(Number);\n\n end = end !== undefined ? end : start;\n ids.push(...Array(end - start + 1).fill().map((_, idx) => start + idx));\n });\n }\n\n return ids;\n }\n /**\n * Groups the data using particular dimensions and by reducing measures. It expects a list of dimensions using which\n * it projects the datamodel and perform aggregations to reduce the duplicate tuples. Refer this\n * {@link link_to_one_example_with_group_by | document} to know the intuition behind groupBy.\n *\n * DataModel by default provides definition of few {@link reducer | Reducers}.\n * {@link ReducerStore | User defined reducers} can also be registered.\n *\n * This is the chained implementation of `groupBy`.\n * `groupBy` also supports {@link link_to_compose_groupBy | composability}\n *\n * @example\n * const groupedDM = dm.groupBy(['Year'], { horsepower: 'max' } );\n * console.log(groupedDm);\n *\n * @public\n *\n * @param {Array.} fieldsArr - Array containing the name of dimensions\n * @param {Object} [reducers={}] - A map whose key is the variable name and value is the name of the reducer. If its\n * not passed, or any variable is ommitted from the object, default aggregation function is used from the\n * schema of the variable.\n *\n * @return {DataModel} Returns a new DataModel instance after performing the groupby.\n */\n groupBy (fieldsArr, reducers = {}, config = { saveChild: true }) {\n const groupByString = `${fieldsArr.join()}`;\n let params = [this, fieldsArr, reducers];\n const newDataModel = groupBy(...params);\n\n persistDerivations(\n this,\n newDataModel,\n DM_DERIVATIVES.GROUPBY,\n { fieldsArr, groupByString, defaultReducer: reducerStore.defaultReducer() },\n reducers\n );\n\n if (config.saveChild) {\n newDataModel.setParent(this);\n } else {\n newDataModel.setParent(null);\n }\n\n return newDataModel;\n }\n\n /**\n * Performs sorting operation on the current {@link DataModel} instance according to the specified sorting details.\n * Like every other operator it doesn't mutate the current DataModel instance on which it was called, instead\n * returns a new DataModel instance containing the sorted data.\n *\n * DataModel support multi level sorting by listing the variables using which sorting needs to be performed and\n * the type of sorting `ASC` or `DESC`.\n *\n * In the following example, data is sorted by `Origin` field in `DESC` order in first level followed by another\n * level of sorting by `Acceleration` in `ASC` order.\n *\n * @example\n * // here dm is the pre-declared DataModel instance containing the data of 'cars.json' file\n * let sortedDm = dm.sort([\n * [\"Origin\", \"DESC\"]\n * [\"Acceleration\"] // Default value is ASC\n * ]);\n *\n * console.log(dm.getData());\n * console.log(sortedDm.getData());\n *\n * // Sort with a custom sorting function\n * sortedDm = dm.sort([\n * [\"Origin\", \"DESC\"]\n * [\"Acceleration\", (a, b) => a - b] // Custom sorting function\n * ]);\n *\n * console.log(dm.getData());\n * console.log(sortedDm.getData());\n *\n * @text\n * DataModel also provides another sorting mechanism out of the box where sort is applied to a variable using\n * another variable which determines the order.\n * Like the above DataModel contains three fields `Origin`, `Name` and `Acceleration`. Now, the data in this\n * model can be sorted by `Origin` field according to the average value of all `Acceleration` for a\n * particular `Origin` value.\n *\n * @example\n * // here dm is the pre-declared DataModel instance containing the data of 'cars.json' file\n * const sortedDm = dm.sort([\n * ['Origin', ['Acceleration', (a, b) => avg(...a.Acceleration) - avg(...b.Acceleration)]]\n * ]);\n *\n * console.log(dm.getData());\n * console.log(sortedDm.getData());\n *\n * @public\n *\n * @param {Array.} sortingDetails - Sorting details based on which the sorting will be performed.\n * @return {DataModel} Returns a new instance of DataModel with sorted data.\n */\n sort (sortingDetails, config = { saveChild: false }) {\n const rawData = this.getData({\n order: 'row',\n sort: sortingDetails\n });\n const header = rawData.schema.map(field => field.name);\n const dataInCSVArr = [header].concat(rawData.data);\n\n const sortedDm = new this.constructor(dataInCSVArr, rawData.schema, { dataFormat: 'DSVArr' });\n\n persistDerivations(\n this,\n sortedDm,\n DM_DERIVATIVES.SORT,\n config,\n sortingDetails\n );\n\n if (config.saveChild) {\n sortedDm.setParent(this);\n } else {\n sortedDm.setParent(null);\n }\n\n return sortedDm;\n }\n\n /**\n * Performs the serialization operation on the current {@link DataModel} instance according to the specified data\n * type. When an {@link DataModel} instance is created, it de-serializes the input data into its internal format,\n * and during its serialization process, it converts its internal data format to the specified data type and returns\n * that data regardless what type of data is used during the {@link DataModel} initialization.\n *\n * @example\n * // here dm is the pre-declared DataModel instance.\n * const csvData = dm.serialize(DataModel.DataFormat.DSV_STR, { fieldSeparator: \",\" });\n * console.log(csvData); // The csv formatted data.\n *\n * const jsonData = dm.serialize(DataModel.DataFormat.FLAT_JSON);\n * console.log(jsonData); // The json data.\n *\n * @public\n *\n * @param {string} type - The data type name for serialization.\n * @param {Object} options - The optional option object.\n * @param {string} options.fieldSeparator - The field separator character for DSV data type.\n * @return {Array|string} Returns the serialized data.\n */\n serialize (type, options) {\n type = type || this._dataFormat;\n options = Object.assign({}, { fieldSeparator: ',' }, options);\n\n const fields = this.getFieldspace().fields;\n const colData = fields.map(f => f.formattedData());\n const rowsCount = colData[0].length;\n let serializedData;\n let rowIdx;\n let colIdx;\n\n if (type === DataFormat.FLAT_JSON) {\n serializedData = [];\n for (rowIdx = 0; rowIdx < rowsCount; rowIdx++) {\n const row = {};\n for (colIdx = 0; colIdx < fields.length; colIdx++) {\n row[fields[colIdx].name()] = colData[colIdx][rowIdx];\n }\n serializedData.push(row);\n }\n } else if (type === DataFormat.DSV_STR) {\n serializedData = [fields.map(f => f.name()).join(options.fieldSeparator)];\n for (rowIdx = 0; rowIdx < rowsCount; rowIdx++) {\n const row = [];\n for (colIdx = 0; colIdx < fields.length; colIdx++) {\n row.push(colData[colIdx][rowIdx]);\n }\n serializedData.push(row.join(options.fieldSeparator));\n }\n serializedData = serializedData.join('\\n');\n } else if (type === DataFormat.DSV_ARR) {\n serializedData = [fields.map(f => f.name())];\n for (rowIdx = 0; rowIdx < rowsCount; rowIdx++) {\n const row = [];\n for (colIdx = 0; colIdx < fields.length; colIdx++) {\n row.push(colData[colIdx][rowIdx]);\n }\n serializedData.push(row);\n }\n } else {\n throw new Error(`Data type ${type} is not supported`);\n }\n\n return serializedData;\n }\n\n addField (field) {\n const fieldName = field.name();\n this._colIdentifier += `,${fieldName}`;\n const partialFieldspace = this._partialFieldspace;\n const cachedValueObjects = partialFieldspace._cachedValueObjects;\n\n if (!partialFieldspace.fieldsObj()[field.name()]) {\n partialFieldspace.fields.push(field);\n cachedValueObjects.forEach((obj, i) => {\n obj[field.name()] = new Value(field.partialField.data[i], field);\n });\n } else {\n const fieldIndex = partialFieldspace.fields.findIndex(fieldinst => fieldinst.name() === fieldName);\n fieldIndex >= 0 && (partialFieldspace.fields[fieldIndex] = field);\n }\n\n // flush out cached namespace values on addition of new fields\n partialFieldspace._cachedFieldsObj = null;\n partialFieldspace._cachedDimension = null;\n partialFieldspace._cachedMeasure = null;\n\n this.__calculateFieldspace().calculateFieldsConfig();\n return this;\n }\n\n /**\n * Creates a new variable calculated from existing variables. This method expects the definition of the newly created\n * variable and a function which resolves the value of the new variable from existing variables.\n *\n * Can create a new measure based on existing variables:\n * @example\n * // DataModel already prepared and assigned to dm variable;\n * const newDm = dataModel.calculateVariable({\n * name: 'powerToWeight',\n * type: 'measure'\n * }, ['horsepower', 'weight_in_lbs', (hp, weight) => hp / weight ]);\n *\n *\n * Can create a new dimension based on existing variables:\n * @example\n * // DataModel already prepared and assigned to dm variable;\n * const child = dataModel.calculateVariable(\n * {\n * name: 'Efficiency',\n * type: 'dimension'\n * }, ['horsepower', (hp) => {\n * if (hp < 80) { return 'low'; },\n * else if (hp < 120) { return 'moderate'; }\n * else { return 'high' }\n * }]);\n *\n * @public\n *\n * @param {Object} schema - The schema of newly defined variable.\n * @param {Array.} dependency - An array containing the dependency variable names and a resolver\n * function as the last element.\n * @param {Object} config - An optional config object.\n * @param {boolean} [config.saveChild] - Whether the newly created DataModel will be a child.\n * @param {boolean} [config.replaceVar] - Whether the newly created variable will replace the existing variable.\n * @return {DataModel} Returns an instance of DataModel with the new field.\n */\n calculateVariable (schema, dependency, config) {\n schema = sanitizeUnitSchema(schema);\n config = Object.assign({}, { saveChild: true, replaceVar: false }, config);\n\n const fieldsConfig = this.getFieldsConfig();\n const depVars = dependency.slice(0, dependency.length - 1);\n const retrieveFn = dependency[dependency.length - 1];\n\n if (fieldsConfig[schema.name] && !config.replaceVar) {\n throw new Error(`${schema.name} field already exists in datamodel`);\n }\n\n const depFieldIndices = depVars.map((field) => {\n const fieldSpec = fieldsConfig[field];\n if (!fieldSpec) {\n // @todo dont throw error here, use warning in production mode\n throw new Error(`${field} is not a valid column name.`);\n }\n return fieldSpec.index;\n });\n\n const clone = this.clone(config.saveChild);\n\n const fs = clone.getFieldspace().fields;\n const suppliedFields = depFieldIndices.map(idx => fs[idx]);\n\n let cachedStore = {};\n let cloneProvider = () => this.detachedRoot();\n\n const computedValues = [];\n rowDiffsetIterator(clone._rowDiffset, (i) => {\n const fieldsData = suppliedFields.map(field => field.partialField.data[i]);\n computedValues[i] = retrieveFn(...fieldsData, i, cloneProvider, cachedStore);\n });\n const [field] = createFields([computedValues], [schema], [schema.name]);\n clone.addField(field);\n\n persistDerivations(\n this,\n clone,\n DM_DERIVATIVES.CAL_VAR,\n { config: schema, fields: depVars },\n retrieveFn\n );\n\n return clone;\n }\n\n /**\n * Propagates changes across all the connected DataModel instances.\n *\n * @param {Array} identifiers - A list of identifiers that were interacted with.\n * @param {Object} payload - The interaction specific details.\n *\n * @return {DataModel} DataModel instance.\n */\n propagate (identifiers, config = {}, addToNameSpace, propConfig = {}) {\n const isMutableAction = config.isMutableAction;\n const propagationSourceId = config.sourceId;\n const payload = config.payload;\n const rootModel = getRootDataModel(this);\n const propagationNameSpace = rootModel._propagationNameSpace;\n const rootGroupByModel = getRootGroupByModel(this);\n const rootModels = {\n groupByModel: rootGroupByModel,\n model: rootModel\n };\n\n addToNameSpace && addToPropNamespace(propagationNameSpace, config, this);\n propagateToAllDataModels(identifiers, rootModels, { propagationNameSpace, sourceId: propagationSourceId },\n Object.assign({\n payload\n }, config));\n\n if (isMutableAction) {\n propagateImmutableActions(propagationNameSpace, rootModels, {\n config,\n propConfig\n }, this);\n }\n\n return this;\n }\n\n /**\n * Associates a callback with an event name.\n *\n * @param {string} eventName - The name of the event.\n * @param {Function} callback - The callback to invoke.\n * @return {DataModel} Returns this current DataModel instance itself.\n */\n on (eventName, callback) {\n switch (eventName) {\n case PROPAGATION:\n this._onPropagation.push(callback);\n break;\n }\n return this;\n }\n\n /**\n * Unsubscribes the callbacks for the provided event name.\n *\n * @param {string} eventName - The name of the event to unsubscribe.\n * @return {DataModel} Returns the current DataModel instance itself.\n */\n unsubscribe (eventName) {\n switch (eventName) {\n case PROPAGATION:\n this._onPropagation = [];\n break;\n\n }\n return this;\n }\n\n /**\n * This method is used to invoke the method associated with propagation.\n *\n * @param {Object} payload The interaction payload.\n * @param {DataModel} identifiers The propagated DataModel.\n * @memberof DataModel\n */\n handlePropagation (propModel, payload) {\n let propListeners = this._onPropagation;\n propListeners.forEach(fn => fn.call(this, propModel, payload));\n }\n\n /**\n * Performs the binning operation on a measure field based on the binning configuration. Binning means discretizing\n * values of a measure. Binning configuration contains an array; subsequent values from the array marks the boundary\n * of buckets in [inclusive, exclusive) range format. This operation does not mutate the subject measure field,\n * instead, it creates a new field (variable) of type dimension and subtype binned.\n *\n * Binning can be configured by\n * - providing custom bin configuration with non-uniform buckets,\n * - providing bins count,\n * - providing each bin size,\n *\n * When custom `buckets` are provided as part of binning configuration:\n * @example\n * // DataModel already prepared and assigned to dm variable\n * const config = { name: 'binnedHP', buckets: [30, 80, 100, 110] }\n * const binnedDM = dataModel.bin('horsepower', config);\n *\n * @text\n * When `binsCount` is defined as part of binning configuration:\n * @example\n * // DataModel already prepared and assigned to dm variable\n * const config = { name: 'binnedHP', binsCount: 5, start: 0, end: 100 }\n * const binDM = dataModel.bin('horsepower', config);\n *\n * @text\n * When `binSize` is defined as part of binning configuration:\n * @example\n * // DataModel already prepared and assigned to dm variable\n * const config = { name: 'binnedHorsepower', binSize: 20, start: 5}\n * const binDM = dataModel.bin('horsepower', config);\n *\n * @public\n *\n * @param {string} measureFieldName - The name of the target measure field.\n * @param {Object} config - The config object.\n * @param {string} [config.name] - The name of the new field which will be created.\n * @param {string} [config.buckets] - An array containing the bucket ranges.\n * @param {string} [config.binSize] - The size of each bin. It is ignored when buckets are given.\n * @param {string} [config.binsCount] - The total number of bins to generate. It is ignored when buckets are given.\n * @param {string} [config.start] - The start value of the bucket ranges. It is ignored when buckets are given.\n * @param {string} [config.end] - The end value of the bucket ranges. It is ignored when buckets are given.\n * @return {DataModel} Returns a new {@link DataModel} instance with the new field.\n */\n bin (measureFieldName, config) {\n const fieldsConfig = this.getFieldsConfig();\n\n if (!fieldsConfig[measureFieldName]) {\n throw new Error(`Field ${measureFieldName} doesn't exist`);\n }\n\n const binFieldName = config.name || `${measureFieldName}_binned`;\n\n if (fieldsConfig[binFieldName]) {\n throw new Error(`Field ${binFieldName} already exists`);\n }\n\n const measureField = this.getFieldspace().fieldsObj()[measureFieldName];\n const { binnedData, bins } = createBinnedFieldData(measureField, this._rowDiffset, config);\n\n const binField = createFields([binnedData], [\n {\n name: binFieldName,\n type: FieldType.DIMENSION,\n subtype: DimensionSubtype.BINNED,\n bins\n }], [binFieldName])[0];\n\n const clone = this.clone(config.saveChild);\n clone.addField(binField);\n\n persistDerivations(\n this,\n clone,\n DM_DERIVATIVES.BIN,\n { measureFieldName, config, binFieldName },\n null\n );\n\n return clone;\n }\n\n /**\n * Creates a new {@link DataModel} instance with completely detached root from current {@link DataModel} instance,\n * the new {@link DataModel} instance has no parent-children relationship with the current one, but has same data as\n * the current one.\n * This API is useful when a completely different {@link DataModel} but with same data as the current instance is\n * needed.\n *\n * @example\n * const dm = new DataModel(data, schema);\n * const detachedDm = dm.detachedRoot();\n *\n * // has different namespace\n * console.log(dm.getPartialFieldspace().name);\n * console.log(detachedDm.getPartialFieldspace().name);\n *\n * // has same data\n * console.log(dm.getData());\n * console.log(detachedDm.getData());\n *\n * @public\n *\n * @return {DataModel} Returns a detached {@link DataModel} instance.\n */\n detachedRoot () {\n const data = this.serialize(DataFormat.FLAT_JSON);\n const schema = this.getSchema();\n\n return new DataModel(data, schema);\n }\n\n /**\n * Creates a set of new {@link DataModel} instances by splitting the set of rows in the source {@link DataModel}\n * instance based on a set of dimensions.\n *\n * For each unique dimensional value, a new split is created which creates a unique {@link DataModel} instance for\n * that split\n *\n * If multiple dimensions are provided, it splits the source {@link DataModel} instance with all possible\n * combinations of the dimensional values for all the dimensions provided\n *\n * Additionally, it also accepts a predicate function to reduce the set of rows provided. A\n * {@link link_to_selection | Selection} is performed on all the split {@link DataModel} instances based on\n * the predicate function\n *\n * @example\n * // without predicate function:\n * const splitDt = dt.splitByRow(['Origin'])\n * console.log(splitDt));\n * // This should give three unique DataModel instances, one each having rows only for 'USA',\n * // 'Europe' and 'Japan' respectively\n *\n * @example\n * // without predicate function:\n * const splitDtMulti = dt.splitByRow(['Origin', 'Cylinders'])\n * console.log(splitDtMulti));\n * // This should give DataModel instances for all unique combinations of Origin and Cylinder values\n *\n * @example\n * // with predicate function:\n * const splitWithPredDt = dt.select(['Origin'], fields => fields.Origin.value === \"USA\")\n * console.log(splitWithPredDt);\n * // This should not include the DataModel for the Origin : 'USA'\n *\n *\n * @public\n *\n * @param {Array} dimensionArr - Set of dimensions based on which the split should occur\n * @param {Object} config - The configuration object\n * @param {string} [config.saveChild] - Configuration to save child or not\n * @param {string}[config.mode=FilteringMode.NORMAL] -The mode of the selection.\n * @return {Array} Returns the new DataModel instances after operation.\n */\n splitByRow (dimensionArr, reducerFn, config) {\n const fieldsConfig = this.getFieldsConfig();\n\n dimensionArr.forEach((fieldName) => {\n if (!fieldsConfig[fieldName]) {\n throw new Error(`Field ${fieldName} doesn't exist in the schema`);\n }\n });\n\n const defConfig = {\n mode: FilteringMode.NORMAL,\n saveChild: true\n };\n\n config = Object.assign({}, defConfig, config);\n\n return splitWithSelect(this, dimensionArr, reducerFn, config);\n }\n\n /**\n * Creates a set of new {@link DataModel} instances by splitting the set of fields in the source {@link DataModel}\n * instance based on a set of common and unique field names provided.\n *\n * Each DataModel created contains a set of fields which are common to all and a set of unique fields.\n * It also accepts configurations such as saveChild and mode(inverse or normal) to include/exclude the respective\n * fields\n *\n * @example\n * // without predicate function:\n * const splitDt = dt.splitByColumn( [['Acceleration'], ['Horsepower']], ['Origin'])\n * console.log(splitDt));\n * // This should give two unique DataModel instances, both having the field 'Origin' and\n * // one each having 'Acceleration' and 'Horsepower' fields respectively\n *\n * @example\n * // without predicate function:\n * const splitDtInv = dt.splitByColumn( [['Acceleration'], ['Horsepower'],['Origin', 'Cylinders'],\n * {mode: 'inverse'})\n * console.log(splitDtInv));\n * // This should give DataModel instances in the following way:\n * // All DataModel Instances do not have the fields 'Origin' and 'Cylinders'\n * // One DataModel Instance has rest of the fields except 'Acceleration' and the other DataModel instance\n * // has rest of the fields except 'Horsepower'\n *\n *\n *\n * @public\n *\n * @param {Array} uniqueFields - Set of unique fields included in each datamModel instance\n * @param {Array} commonFields - Set of common fields included in all datamModel instances\n * @param {Object} config - The configuration object\n * @param {string} [config.saveChild] - Configuration to save child or not\n * @param {string}[config.mode=FilteringMode.NORMAL] -The mode of the selection.\n * @return {Array} Returns the new DataModel instances after operation.\n */\n splitByColumn (uniqueFields = [], commonFields = [], config) {\n const defConfig = {\n mode: FilteringMode.NORMAL,\n saveChild: true\n };\n const fieldConfig = this.getFieldsConfig();\n const allFields = Object.keys(fieldConfig);\n const normalizedProjFieldSets = [[commonFields]];\n\n config = Object.assign({}, defConfig, config);\n uniqueFields = uniqueFields.length ? uniqueFields : [[]];\n\n\n uniqueFields.forEach((fieldSet, i) => {\n normalizedProjFieldSets[i] = getNormalizedProFields(\n [...fieldSet, ...commonFields],\n allFields,\n fieldConfig);\n });\n\n return splitWithProject(this, normalizedProjFieldSets, config, allFields);\n }\n\n\n}\n\nexport default DataModel;\n","import { fnList } from '../operator/group-by-function';\n\nexport const { sum, avg, min, max, first, last, count, std: sd } = fnList;\n","import DataModel from './datamodel';\nimport {\n compose,\n bin,\n select,\n project,\n groupby as groupBy,\n calculateVariable,\n sort,\n crossProduct,\n difference,\n naturalJoin,\n leftOuterJoin,\n rightOuterJoin,\n fullOuterJoin,\n union\n} from './operator';\nimport * as Stats from './stats';\nimport * as enums from './enums';\nimport { DateTimeFormatter } from './utils';\nimport { DataFormat, FilteringMode, DM_DERIVATIVES } from './constants';\nimport InvalidAwareTypes from './invalid-aware-types';\nimport pkg from '../package.json';\n\nconst Operators = {\n compose,\n bin,\n select,\n project,\n groupBy,\n calculateVariable,\n sort,\n crossProduct,\n difference,\n naturalJoin,\n leftOuterJoin,\n rightOuterJoin,\n fullOuterJoin,\n union\n};\n\nconst version = pkg.version;\nObject.assign(DataModel, {\n Operators,\n Stats,\n DM_DERIVATIVES,\n DateTimeFormatter,\n DataFormat,\n FilteringMode,\n InvalidAwareTypes,\n version\n}, enums);\n\nexport default DataModel;\n","/**\n * Wrapper on calculateVariable() method of DataModel to behave\n * the pure-function functionality.\n *\n * @param {Array} args - The argument list.\n * @return {any} Returns the returned value of calling function.\n */\nexport const calculateVariable = (...args) => dm => dm.calculateVariable(...args);\n\n/**\n * Wrapper on sort() method of DataModel to behave\n * the pure-function functionality.\n *\n * @param {Array} args - The argument list.\n * @return {any} Returns the returned value of calling function.\n */\nexport const sort = (...args) => dm => dm.sort(...args);\n","import { crossProduct } from './cross-product';\nimport { naturalJoinFilter } from './natural-join-filter-function';\n\nexport function naturalJoin (dataModel1, dataModel2) {\n return crossProduct(dataModel1, dataModel2, naturalJoinFilter(dataModel1, dataModel2), true);\n}\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://DataModel/webpack/universalModuleDefinition","webpack://DataModel/webpack/bootstrap","webpack://DataModel/./src/index.js","webpack://DataModel/./src/enums/data-format.js","webpack://DataModel/./src/enums/dimension-subtype.js","webpack://DataModel/./src/enums/measure-subtype.js","webpack://DataModel/./src/enums/field-type.js","webpack://DataModel/./src/enums/filtering-mode.js","webpack://DataModel/./src/enums/group-by-functions.js","webpack://DataModel/./src/utils/date-time-formatter.js","webpack://DataModel/./src/utils/column-major.js","webpack://DataModel/./src/utils/extend2.js","webpack://DataModel/./src/utils/helper.js","webpack://DataModel/./src/field-store.js","webpack://DataModel/./src/value.js","webpack://DataModel/./src/operator/row-diffset-iterator.js","webpack://DataModel/./src/invalid-aware-types.js","webpack://DataModel/./src/operator/bucket-creator.js","webpack://DataModel/./src/constants/index.js","webpack://DataModel/./src/operator/get-common-schema.js","webpack://DataModel/./src/operator/cross-product.js","webpack://DataModel/./src/operator/merge-sort.js","webpack://DataModel/./src/operator/sort.js","webpack://DataModel/./src/operator/data-builder.js","webpack://DataModel/./src/operator/difference.js","webpack://DataModel/./src/operator/group-by-function.js","webpack://DataModel/./src/utils/reducer-store.js","webpack://DataModel/./src/operator/group-by.js","webpack://DataModel/./src/operator/natural-join-filter-function.js","webpack://DataModel/./src/operator/union.js","webpack://DataModel/./src/operator/outer-join.js","webpack://DataModel/./src/fields/field/index.js","webpack://DataModel/./src/fields/dimension/index.js","webpack://DataModel/./src/fields/categorical/index.js","webpack://DataModel/./src/fields/temporal/index.js","webpack://DataModel/./src/fields/binned/index.js","webpack://DataModel/./src/fields/measure/index.js","webpack://DataModel/./src/fields/continuous/index.js","webpack://DataModel/./src/fields/parsers/field-parser/index.js","webpack://DataModel/./src/fields/parsers/categorical-parser/index.js","webpack://DataModel/./src/fields/parsers/temporal-parser/index.js","webpack://DataModel/./src/fields/parsers/binned-parser/index.js","webpack://DataModel/./src/fields/parsers/continuous-parser/index.js","webpack://DataModel/./src/fields/partial-field/index.js","webpack://DataModel/./src/field-creator.js","webpack://DataModel/./src/default-config.js","webpack://DataModel/./src/converter/dsv-arr.js","webpack://DataModel/./node_modules/d3-dsv/src/dsv.js","webpack://DataModel/./node_modules/d3-dsv/src/csv.js","webpack://DataModel/./node_modules/d3-dsv/src/tsv.js","webpack://DataModel/./src/converter/dsv-str.js","webpack://DataModel/./src/converter/flat-json.js","webpack://DataModel/./src/converter/auto-resolver.js","webpack://DataModel/./src/helper.js","webpack://DataModel/./src/relation.js","webpack://DataModel/./src/datamodel.js","webpack://DataModel/./src/stats/index.js","webpack://DataModel/./src/export.js","webpack://DataModel/./src/operator/compose.js","webpack://DataModel/./src/operator/pure-operators.js","webpack://DataModel/./src/operator/natural-join.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","DataModel","require","default","DataFormat","FLAT_JSON","DSV_STR","DSV_ARR","AUTO","DimensionSubtype","CATEGORICAL","TEMPORAL","GEO","BINNED","MeasureSubtype","CONTINUOUS","FieldType","MEASURE","DIMENSION","FilteringMode","NORMAL","INVERSE","ALL","GROUP_BY_FUNCTIONS","SUM","AVG","MIN","MAX","FIRST","LAST","COUNT","STD","convertToNativeDate","date","Date","pad","DateTimeFormatter","format","this","dtParams","undefined","nativeDate","RegExp","escape","text","replace","TOKEN_PREFIX","DATETIME_PARAM_SEQUENCE","YEAR","MONTH","DAY","HOUR","MINUTE","SECOND","MILLISECOND","defaultNumberParser","defVal","val","parsedVal","isFinite","parseInt","defaultRangeParser","range","nVal","toLowerCase","length","getTokenDefinitions","daysDef","short","long","monthsDef","H","index","extract","parser","formatter","getHours","toString","hours","P","M","getMinutes","S","getSeconds","K","getMilliseconds","a","join","day","getDay","A","e","getDate","b","month","getMonth","B","y","result","substring","presentDate","presentYear","Math","trunc","getFullYear","year","Y","getTokenFormalNames","definitions","HOUR_12","AMPM_UPPERCASE","AMPM_LOWERCASE","SHORT_DAY","LONG_DAY","DAY_OF_MONTH","DAY_OF_MONTH_CONSTANT_WIDTH","SHORT_MONTH","LONG_MONTH","MONTH_OF_YEAR","SHORT_YEAR","LONG_YEAR","tokenResolver","defaultResolver","arg","targetParam","hourFormat24","hourFormat12","ampmLower","ampmUpper","amOrpm","isPM","findTokens","tokenPrefix","tokenLiterals","keys","occurrence","forwardChar","indexOf","push","token","formatAs","nDate","formattedStr","String","formattedVal","parse","dateTimeStamp","options","extractTokenValue","dtParamSeq","noBreak","dtParamArr","args","resolverKey","resolverParams","resolverFn","param","resolvedVal","splice","apply","checkIfOnlyYear","unshift","tokenObj","lastOccurrenceIndex","occObj","occIndex","targetText","regexFormat","tokenArr","map","obj","occurrenceLength","extractValues","match","shift","getNativeDate","Number","len","store","fields","forEach","fieldIndex","Array","from","OBJECTSTRING","objectToStrFn","objectToStr","arrayToStr","checkCyclicRef","parentArr","bIndex","extend2","obj1","obj2","skipUndef","merge","tgtArr","srcArr","item","srcVal","tgtVal","str","cRef","isArray","getUniqueId","getTime","round","random","isArrEqual","arr1","arr2","formatNumber","detectDataFormat","data","isObject","fieldStore","createNamespace","fieldArr","dataId","fieldsObj","_cachedFieldsObj","field","getMeasure","measureFields","_cachedMeasure","schema","type","getDimension","dimensionFields","_cachedDimension","Value","rawValue","formattedValue","getNumberFormattedVal","defineProperties","_value","configurable","writable","_formattedValue","_internalValue","rowDiffsetIterator","rowDiffset","callback","split","diffStr","diffStsArr","start","end","InvalidAwareTypes","config","assign","_invalidAwareValsMap","invalidAwareVals","NULL","NA","NIL","invalid","nil","null","generateBuckets","binSize","buckets","next","findBucketRange","bucketRanges","leftIdx","rightIdx","midIdx","floor","DM_DERIVATIVES","SELECT","PROJECT","GROUPBY","COMPOSE","CAL_VAR","BIN","SORT","JOINS","CROSS","LEFTOUTER","RIGHTOUTER","NATURAL","FULLOUTER","LOGICAL_OPERATORS","getCommonSchema","fs1","fs2","retArr","fs1Arr","defaultFilterFn","crossProduct","dm1","dm2","filterFn","replaceCommonSchema","jointype","applicableFilterFn","dm1FieldStore","getFieldspace","dm2FieldStore","dm1FieldStoreName","dm2FieldStoreName","commonSchemaList","Error","tmpSchema","_rowDiffset","rowAdded","rowPosition","ii","tuple","userArg","partialField","formattedData","dm1Fields","prepareJoinData","dm2Fields","detachedRoot","tupleObj","cellVal","iii","defSortFn","a1","b1","mergeSort","arr","sortFn","sort","lo","hi","mid","mainArr","auxArr","resolveStrSortOrder","fDetails","strSortOrder","sortOrder","dataType","sortType","retFunc","getSortFn","groupData","hashMap","Map","groupedData","datum","fieldVal","has","set","createSortingFnArg","groupedDatum","targetFields","targetFieldDetails","label","reduce","acc","idx","applyStandardSort","sortingDetails","fieldName","sortMeta","fieldInSchema","sortingFn","slice","f","makeGroupMapAndSort","depColumns","targetCol","currRow","fVal","nMap","sortData","dataObj","filter","sDetial","groupSortingIdx","findIndex","standardSortingDetails","groupSortingDetails","detail","sortedGroupMap","row","nextMap","applyGroupSort","uids","pop","dataBuilder","colIdentifier","addUid","columnWise","retObj","reqSorting","tmpDataArr","colName","insertInd","tmpData","difference","hashTable","schemaNameArr","dm1FieldStoreFieldObj","dm2FieldStoreFieldObj","_colIdentifier","prepareDataHelper","dm","addData","hashData","schemaName","getFilteredValues","sum","filteredNumber","curr","avg","totalSum","isNaN","fnList","filteredValues","min","max","sqrt","mean","num","variance","defaultReducerName","ReducerStore","defReducer","entries","reducer","__unregister","delete","Function","reducerStore","groupBy","dataModel","reducers","existingDataModel","sFieldArr","dimensions","getFieldArr","reducerObj","measures","defaultReducer","measureName","defAggFn","reducerFn","resolve","getReducerObj","fieldStoreObj","dbName","dimensionArr","measureArr","newDataModel","rowCount","hash","_","cachedStore","cloneProvider","__calculateFieldspace","naturalJoinFilter","commonSchemaArr","retainTuple","internalValue","union","leftOuterJoin","dataModel1","dataModel2","rightOuterJoin","Field","subtype","description","displayName","Dimension","_cachedDomain","calculateDataDomain","Categorical","Set","domain","add","Temporal","_cachedMinDiff","sortedData","arrLn","minDiff","POSITIVE_INFINITY","prevDatum","nextDatum","processedCount","dataFormat","isInvalid","parsedDatum","getInvalidType","Binned","binsArr","bins","Measure","unit","numberFormat","Continuous","NEGATIVE_INFINITY","FieldParser","CategoricalParser","trim","TemporalParser","_dtf","BinnedParser","matched","parseFloat","ContinuousParser","PartialField","_sanitize","createFields","dataColumn","headers","headersObj","header","createUnitField","DSVArr","schemaFields","unitSchema","firstRowHeader","columns","columnMajor","EOL","EOF","QUOTE","NEWLINE","RETURN","objectConverter","JSON","stringify","inferColumns","rows","columnSet","column","width","formatDate","getUTCHours","minutes","getUTCMinutes","seconds","getUTCSeconds","milliseconds","getUTCMilliseconds","getUTCFullYear","getUTCMonth","getUTCDate","delimiter","reFormat","DELIMITER","charCodeAt","parseRows","N","I","eof","eol","j","preformatBody","formatValue","formatRow","test","convert","customConverter","concat","formatBody","formatRows","csv","dsv","tsv","DSVStr","fieldSeparator","d3Dsv","FlatJSON","insertionIndex","schemaFieldsName","Auto","converters","prepareSelectionData","rawData","resp","updateFields","partialFieldspace","fieldStoreName","collID","partialFieldMap","newFields","coll","createUnitFieldFromPartial","persistCurrentDerivation","model","operation","criteriaFn","_derivation","op","meta","criteria","persistAncestorDerivation","sourceDm","newDm","_ancestorDerivation","persistDerivations","selectModeMap","diffIndex","calcDiff","generateRowDiffset","lastInsertedValue","li","selectRowDiffsetIterator","checker","newRowDiffSet","rejRowDiffSet","shouldSelect","shouldReject","checkerResult","rejectRowDiffset","rowSplitDiffsetIterator","splitRowDiffset","dimensionMap","dimensionSet","selectHelper","clonedDm","selectFn","iterator","getPartialFieldspace","formattedFieldsData","rawFieldsData","cloneWithAllFields","clone","calculateFieldsConfig","getKey","fn","filterPropagationModel","propModels","fns","filterByMeasure","clonedModel","modelFieldsConfig","getFieldsConfig","propModel","keyFn","getData","fieldsConfig","dLen","indices","fieldsSpace","v","valuesMap","present","every","select","saveChild","some","addDiffsetToClonedDm","selectConfig","cloneWithProject","projField","allFields","cloned","projectionSet","actualProjField","splitWithProject","projFieldSet","projFields","sanitizeUnitSchema","sanitizeAndValidateSchema","supportedMeasureSubTypes","supportedDimSubTypes","validateUnitSchema","updateData","relation","defaultConfig","converterFn","converter","dataHeader","fieldNameAs","as","resolveFieldName","nameSpace","_partialFieldspace","valueObjects","_cachedValueObjects","_dataFormat","applyExistingOperationOnModel","derivations","getDerivations","selectionModel","derivation","params","groupByString","getDerivationArguments","propagateIdentifiers","propModelInf","nonTraversingModel","excludeModels","propagate","handlePropagation","children","_children","child","getRootGroupByModel","_parent","find","getRootDataModel","getPathToRootModel","path","propagateToAllDataModels","identifiers","rootModels","propagationInf","propagationNameSpace","propagateToSource","propagationSourceId","sourceId","propagateInterpolatedValues","criterias","persistent","actionCriterias","values","mutableActions","filteredCriteria","entry","action","sourceActionCriterias","actionInf","actionConf","applyOnSource","models","rootModel","propConfig","sourceIdentifiers","rootGroupByModel","groupByModel","inf","propagationModel","filteredModel","getFilteredModel","reverse","propagateImmutableActions","immutableActions","filterImmutableAction","criteriaModel","addToPropNamespace","sourceNamespace","isMutableAction","getNormalizedProFields","fieldConfig","normalizedProjField","constructor","search","Relation","source","_fieldStoreName","_propagationNameSpace","_fieldspace","joinWith","unionWith","differenceWith","defConfig","cloneConfig","extraCloneDm","setOfRowDiffsets","cloneWithSelect","setParent","_fieldConfig","fieldObj","def","removeChild","sibling","parent","_onPropagation","order","withUid","getAllFields","dataGenerated","fieldNames","fmtFieldIdx","elem","fIdx","fmtFn","datumIdx","ids","fill","fieldsArr","dataInCSVArr","sortedDm","colData","rowsCount","serializedData","rowIdx","colIdx","cachedValueObjects","fieldinst","dependency","replaceVar","depVars","retrieveFn","depFieldIndices","fieldSpec","fs","suppliedFields","computedValues","fieldsData","addField","addToNameSpace","payload","eventName","measureFieldName","binFieldName","measureField","binsCount","dMin","dMax","ceil","abs","binnedData","createBinnedFieldData","binField","serialize","getSchema","clonedDMs","splitWithSelect","uniqueFields","commonFields","normalizedProjFieldSets","fieldSet","first","last","count","sd","std","Operators","compose","operations","currentDM","firstChild","dispose","bin","project","calculateVariable","naturalJoin","fullOuterJoin","version","Stats","enums"],"mappings":"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","file":"datamodel.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"DataModel\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"DataModel\"] = factory();\n\telse\n\t\troot[\"DataModel\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","const DataModel = require('./export');\n\nmodule.exports = DataModel.default ? DataModel.default : DataModel;\n","/**\n * DataFormat Enum defines the format of the input data.\n * Based on the format of the data the respective adapter is loaded.\n *\n * @readonly\n * @enum {string}\n */\nconst DataFormat = {\n FLAT_JSON: 'FlatJSON',\n DSV_STR: 'DSVStr',\n DSV_ARR: 'DSVArr',\n AUTO: 'Auto'\n};\n\nexport default DataFormat;\n","/**\n * DimensionSubtype enum defines the sub types of the Dimensional Field.\n *\n * @readonly\n * @enum {string}\n */\nconst DimensionSubtype = {\n CATEGORICAL: 'categorical',\n TEMPORAL: 'temporal',\n GEO: 'geo',\n BINNED: 'binned'\n};\n\nexport default DimensionSubtype;\n","/**\n * MeasureSubtype enum defines the sub types of the Measure Field.\n *\n * @readonly\n * @enum {string}\n */\nconst MeasureSubtype = {\n CONTINUOUS: 'continuous'\n};\n\nexport default MeasureSubtype;\n","/**\n * FieldType enum defines the high level field based on which visuals are controlled.\n * Measure in a high level is numeric field and Dimension in a high level is string field.\n *\n * @readonly\n * @enum {string}\n */\nconst FieldType = {\n MEASURE: 'measure',\n DIMENSION: 'dimension'\n};\n\nexport default FieldType;\n","/**\n * Filtering mode enum defines the filering modes of DataModel.\n *\n * @readonly\n * @enum {string}\n */\nconst FilteringMode = {\n NORMAL: 'normal',\n INVERSE: 'inverse',\n ALL: 'all'\n};\n\nexport default FilteringMode;\n","/**\n * Group by function names\n *\n * @readonly\n * @enum {string}\n */\nconst GROUP_BY_FUNCTIONS = {\n SUM: 'sum',\n AVG: 'avg',\n MIN: 'min',\n MAX: 'max',\n FIRST: 'first',\n LAST: 'last',\n COUNT: 'count',\n STD: 'std'\n};\n\nexport default GROUP_BY_FUNCTIONS;\n","/**\n * Creates a JS native date object from input\n *\n * @param {string | number | Date} date Input using which date object to be created\n * @return {Date} : JS native date object\n */\nfunction convertToNativeDate (date) {\n if (date instanceof Date) {\n return date;\n }\n\n return new Date(date);\n}\n/**\n * Apply padding before a number if its less than 1o. This is used when constant digit's number to be returned\n * between 0 - 99\n *\n * @param {number} n Input to be padded\n * @return {string} Padded number\n */\nfunction pad (n) {\n return (n < 10) ? (`0${n}`) : n;\n}\n/*\n * DateFormatter utility to convert any date format to any other date format\n * DateFormatter parse a date time stamp specified by a user abiding by rules which are defined\n * by user in terms of token. It creates JS native date object from the user specified format.\n * That native date can also be displayed\n * in any specified format.\n * This utility class only takes care of format conversion only\n */\n\n/*\n * Escapes all the special character that are used in regular expression.\n * Like\n * RegExp.escape('sgfd-$') // Output: sgfd\\-\\$\n *\n * @param text {String} : text which is to be escaped\n */\nRegExp.escape = function (text) {\n return text.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n};\n\n/**\n * DateTimeFormatter class to convert any user format of date time stamp to any other format\n * of date time stamp.\n *\n * @param {string} format Format of the date given. For the above date,\n * 'year: %Y, month: %b, day: %d'.\n * @class\n */\n/* istanbul ignore next */ function DateTimeFormatter (format) {\n this.format = format;\n this.dtParams = undefined;\n this.nativeDate = undefined;\n}\n\n// The identifier of the tokens\nDateTimeFormatter.TOKEN_PREFIX = '%';\n\n// JS native Date constructor takes the date params (year, month, etc) in a certail sequence.\n// This defines the sequence of the date parameters in the constructor.\nDateTimeFormatter.DATETIME_PARAM_SEQUENCE = {\n YEAR: 0,\n MONTH: 1,\n DAY: 2,\n HOUR: 3,\n MINUTE: 4,\n SECOND: 5,\n MILLISECOND: 6\n};\n\n/*\n * This is a default number parsing utility. It tries to parse a number in integer, if parsing is unsuccessful, it\n * gives back a default value.\n *\n * @param: defVal {Number} : Default no if the parsing to integer is not successful\n * @return {Function} : An closure function which is to be called by passing an the value which needs to be parsed.\n */\nDateTimeFormatter.defaultNumberParser = function (defVal) {\n return function (val) {\n let parsedVal;\n if (isFinite(parsedVal = parseInt(val, 10))) {\n return parsedVal;\n }\n\n return defVal;\n };\n};\n\n/*\n * This is a default number range utility. It tries to find an element in the range. If not found it returns a\n * default no as an index.\n *\n * @param: range {Array} : The list which is to be serached\n * @param: defVal {Number} : Default no if the serach and find does not return anything\n * @return {Function} : An closure function which is to be called by passing an the value which needs to be found\n */\nDateTimeFormatter.defaultRangeParser = function (range, defVal) {\n return (val) => {\n let i;\n let l;\n\n if (!val) { return defVal; }\n\n const nVal = val.toLowerCase();\n\n for (i = 0, l = range.length; i < l; i++) {\n if (range[i].toLowerCase() === nVal) {\n return i;\n }\n }\n\n if (i === undefined) {\n return defVal;\n }\n return null;\n };\n};\n\n/*\n * Defines the tokens which are supporter by the dateformatter. Using this definitation a value gets extracted from\n * the user specifed date string. This also formats the value for display purpose from native JS date.\n * The definition of each token contains the following named properties\n * {\n * %token_name% : {\n * name: name of the token, this is used in reverse lookup,\n * extract: a function that returns the regular expression to extract that piece of information. All the\n * regex should be gouped by using ()\n * parser: a function which receives value extracted by the above regex and parse it to get the date params\n * formatter: a formatter function that takes milliseconds or JS Date object and format the param\n * represented by the token only.\n * }\n * }\n *\n * @return {Object} : Definition of the all the supported tokens.\n */\nDateTimeFormatter.getTokenDefinitions = function () {\n const daysDef = {\n short: [\n 'Sun',\n 'Mon',\n 'Tue',\n 'Wed',\n 'Thu',\n 'Fri',\n 'Sat'\n ],\n long: [\n 'Sunday',\n 'Monday',\n 'Tuesday',\n 'Wednesday',\n 'Thursday',\n 'Friday',\n 'Saturday'\n ]\n };\n const monthsDef = {\n short: [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec'\n ],\n long: [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December'\n ]\n };\n\n const definitions = {\n H: {\n // 24 hours format\n name: 'H',\n index: 3,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n\n return d.getHours().toString();\n }\n },\n l: {\n // 12 hours format\n name: 'l',\n index: 3,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const hours = d.getHours() % 12;\n\n return (hours === 0 ? 12 : hours).toString();\n }\n },\n p: {\n // AM or PM\n name: 'p',\n index: 3,\n extract () { return '(AM|PM)'; },\n parser: (val) => {\n if (val) {\n return val.toLowerCase();\n }\n return null;\n },\n formatter: (val) => {\n const d = convertToNativeDate(val);\n const hours = d.getHours();\n\n return (hours < 12 ? 'AM' : 'PM');\n }\n },\n P: {\n // am or pm\n name: 'P',\n index: 3,\n extract () { return '(am|pm)'; },\n parser: (val) => {\n if (val) {\n return val.toLowerCase();\n }\n return null;\n },\n formatter: (val) => {\n const d = convertToNativeDate(val);\n const hours = d.getHours();\n\n return (hours < 12 ? 'am' : 'pm');\n }\n },\n M: {\n // Two digit minutes 00 - 59\n name: 'M',\n index: 4,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const mins = d.getMinutes();\n\n return pad(mins);\n }\n },\n S: {\n // Two digit seconds 00 - 59\n name: 'S',\n index: 5,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const seconds = d.getSeconds();\n\n return pad(seconds);\n }\n },\n K: {\n // Milliseconds\n name: 'K',\n index: 6,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const ms = d.getMilliseconds();\n\n return ms.toString();\n }\n },\n a: {\n // Short name of day, like Mon\n name: 'a',\n index: 2,\n extract () { return `(${daysDef.short.join('|')})`; },\n parser: DateTimeFormatter.defaultRangeParser(daysDef.short),\n formatter (val) {\n const d = convertToNativeDate(val);\n const day = d.getDay();\n\n return (daysDef.short[day]).toString();\n }\n },\n A: {\n // Long name of day, like Monday\n name: 'A',\n index: 2,\n extract () { return `(${daysDef.long.join('|')})`; },\n parser: DateTimeFormatter.defaultRangeParser(daysDef.long),\n formatter (val) {\n const d = convertToNativeDate(val);\n const day = d.getDay();\n\n return (daysDef.long[day]).toString();\n }\n },\n e: {\n // 8 of March, 11 of November\n name: 'e',\n index: 2,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const day = d.getDate();\n\n return day.toString();\n }\n },\n d: {\n // 08 of March, 11 of November\n name: 'd',\n index: 2,\n extract () { return '(\\\\d+)'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const day = d.getDate();\n\n return pad(day);\n }\n },\n b: {\n // Short month, like Jan\n name: 'b',\n index: 1,\n extract () { return `(${monthsDef.short.join('|')})`; },\n parser: DateTimeFormatter.defaultRangeParser(monthsDef.short),\n formatter (val) {\n const d = convertToNativeDate(val);\n const month = d.getMonth();\n\n return (monthsDef.short[month]).toString();\n }\n },\n B: {\n // Long month, like January\n name: 'B',\n index: 1,\n extract () { return `(${monthsDef.long.join('|')})`; },\n parser: DateTimeFormatter.defaultRangeParser(monthsDef.long),\n formatter (val) {\n const d = convertToNativeDate(val);\n const month = d.getMonth();\n\n return (monthsDef.long[month]).toString();\n }\n },\n m: {\n // Two digit month of year like 01 for January\n name: 'm',\n index: 1,\n extract () { return '(\\\\d+)'; },\n parser (val) { return DateTimeFormatter.defaultNumberParser()(val) - 1; },\n formatter (val) {\n const d = convertToNativeDate(val);\n const month = d.getMonth();\n\n return pad(month + 1);\n }\n },\n y: {\n // Short year like 90 for 1990\n name: 'y',\n index: 0,\n extract () { return '(\\\\d{2})'; },\n parser (val) {\n let result;\n if (val) {\n const l = val.length;\n val = val.substring(l - 2, l);\n }\n let parsedVal = DateTimeFormatter.defaultNumberParser()(val);\n let presentDate = new Date();\n let presentYear = Math.trunc((presentDate.getFullYear()) / 100);\n\n result = `${presentYear}${parsedVal}`;\n\n if (convertToNativeDate(result).getFullYear() > presentDate.getFullYear()) {\n result = `${presentYear - 1}${parsedVal}`;\n }\n return convertToNativeDate(result).getFullYear();\n },\n formatter (val) {\n const d = convertToNativeDate(val);\n let year = d.getFullYear().toString();\n let l;\n\n if (year) {\n l = year.length;\n year = year.substring(l - 2, l);\n }\n\n return year;\n }\n },\n Y: {\n // Long year like 1990\n name: 'Y',\n index: 0,\n extract () { return '(\\\\d{4})'; },\n parser: DateTimeFormatter.defaultNumberParser(),\n formatter (val) {\n const d = convertToNativeDate(val);\n const year = d.getFullYear().toString();\n\n return year;\n }\n }\n };\n\n return definitions;\n};\n\n/*\n * The tokens which works internally is not user friendly in terms of memorizing the names. This gives a formal\n * definition to the informal notations.\n *\n * @return {Object} : Formal definition of the tokens\n */\nDateTimeFormatter.getTokenFormalNames = function () {\n const definitions = DateTimeFormatter.getTokenDefinitions();\n\n return {\n HOUR: definitions.H,\n HOUR_12: definitions.l,\n AMPM_UPPERCASE: definitions.p,\n AMPM_LOWERCASE: definitions.P,\n MINUTE: definitions.M,\n SECOND: definitions.S,\n SHORT_DAY: definitions.a,\n LONG_DAY: definitions.A,\n DAY_OF_MONTH: definitions.e,\n DAY_OF_MONTH_CONSTANT_WIDTH: definitions.d,\n SHORT_MONTH: definitions.b,\n LONG_MONTH: definitions.B,\n MONTH_OF_YEAR: definitions.m,\n SHORT_YEAR: definitions.y,\n LONG_YEAR: definitions.Y\n };\n};\n\n/*\n * This defines the rules and declares dependencies that resolves a date parameter (year, month etc) from\n * the date time parameter array.\n *\n * @return {Object} : An object that contains dependencies and a resolver function. The dependencies values are fed\n * to the resolver function in that particular sequence only.\n */\nDateTimeFormatter.tokenResolver = function () {\n const definitions = DateTimeFormatter.getTokenDefinitions();\n const defaultResolver = (...args) => { // eslint-disable-line require-jsdoc\n let i = 0;\n let arg;\n let targetParam;\n const l = args.length;\n\n for (; i < l; i++) {\n arg = args[i];\n if (args[i]) {\n targetParam = arg;\n }\n }\n\n if (!targetParam) { return null; }\n\n return targetParam[0].parser(targetParam[1]);\n };\n\n return {\n YEAR: [definitions.y, definitions.Y,\n defaultResolver\n ],\n MONTH: [definitions.b, definitions.B, definitions.m,\n defaultResolver\n ],\n DAY: [definitions.a, definitions.A, definitions.e, definitions.d,\n defaultResolver\n ],\n HOUR: [definitions.H, definitions.l, definitions.p, definitions.P,\n function (hourFormat24, hourFormat12, ampmLower, ampmUpper) {\n let targetParam;\n let amOrpm;\n let isPM;\n let val;\n\n if (hourFormat12 && (amOrpm = (ampmLower || ampmUpper))) {\n if (amOrpm[0].parser(amOrpm[1]) === 'pm') {\n isPM = true;\n }\n\n targetParam = hourFormat12;\n } else if (hourFormat12) {\n targetParam = hourFormat12;\n } else {\n targetParam = hourFormat24;\n }\n\n if (!targetParam) { return null; }\n\n val = targetParam[0].parser(targetParam[1]);\n if (isPM) {\n val += 12;\n }\n return val;\n }\n ],\n MINUTE: [definitions.M,\n defaultResolver\n ],\n SECOND: [definitions.S,\n defaultResolver\n ]\n };\n};\n\n/*\n * Finds token from the format rule specified by a user.\n * @param format {String} : The format of the input date specified by the user\n * @return {Array} : An array of objects which contains the available token and their occurence index in the format\n */\nDateTimeFormatter.findTokens = function (format) {\n const tokenPrefix = DateTimeFormatter.TOKEN_PREFIX;\n const definitions = DateTimeFormatter.getTokenDefinitions();\n const tokenLiterals = Object.keys(definitions);\n const occurrence = [];\n let i;\n let forwardChar;\n\n while ((i = format.indexOf(tokenPrefix, i + 1)) >= 0) {\n forwardChar = format[i + 1];\n if (tokenLiterals.indexOf(forwardChar) === -1) { continue; }\n\n occurrence.push({\n index: i,\n token: forwardChar\n });\n }\n\n return occurrence;\n};\n\n/*\n * Format any JS date to a specified date given by user.\n *\n * @param date {Number | Date} : The date object which is to be formatted\n * @param format {String} : The format using which the date will be formatted for display\n */\nDateTimeFormatter.formatAs = function (date, format) {\n const nDate = convertToNativeDate(date);\n const occurrence = DateTimeFormatter.findTokens(format);\n const definitions = DateTimeFormatter.getTokenDefinitions();\n let formattedStr = String(format);\n const tokenPrefix = DateTimeFormatter.TOKEN_PREFIX;\n let token;\n let formattedVal;\n let i;\n let l;\n\n for (i = 0, l = occurrence.length; i < l; i++) {\n token = occurrence[i].token;\n formattedVal = definitions[token].formatter(nDate);\n formattedStr = formattedStr.replace(new RegExp(tokenPrefix + token, 'g'), formattedVal);\n }\n\n return formattedStr;\n};\n\n/*\n * Parses the user specified date string to extract the date time params.\n *\n * @return {Array} : Value of date time params in an array [year, month, day, hour, minutes, seconds, milli]\n */\nDateTimeFormatter.prototype.parse = function (dateTimeStamp, options) {\n const tokenResolver = DateTimeFormatter.tokenResolver();\n const dtParams = this.extractTokenValue(dateTimeStamp);\n const dtParamSeq = DateTimeFormatter.DATETIME_PARAM_SEQUENCE;\n const noBreak = options && options.noBreak;\n const dtParamArr = [];\n const args = [];\n let resolverKey;\n let resolverParams;\n let resolverFn;\n let val;\n let i;\n let param;\n let resolvedVal;\n let l;\n let result = [];\n\n for (resolverKey in tokenResolver) {\n if (!{}.hasOwnProperty.call(tokenResolver, resolverKey)) { continue; }\n\n args.length = 0;\n resolverParams = tokenResolver[resolverKey];\n resolverFn = resolverParams.splice(resolverParams.length - 1, 1)[0];\n\n for (i = 0, l = resolverParams.length; i < l; i++) {\n param = resolverParams[i];\n val = dtParams[param.name];\n\n if (val === undefined) {\n args.push(null);\n } else {\n args.push([param, val]);\n }\n }\n\n resolvedVal = resolverFn.apply(this, args);\n\n if ((resolvedVal === undefined || resolvedVal === null) && !noBreak) {\n break;\n }\n\n dtParamArr[dtParamSeq[resolverKey]] = resolvedVal;\n }\n\n if (dtParamArr.length && this.checkIfOnlyYear(dtParamArr.length))\n {\n result.unshift(dtParamArr[0], 0, 1); }\n else {\n result.unshift(...dtParamArr);\n }\n\n return result;\n};\n\n/*\n * Extract the value of the token from user specified date time string.\n *\n * @return {Object} : An key value pair which contains the tokens as key and value as pair\n */\nDateTimeFormatter.prototype.extractTokenValue = function (dateTimeStamp) {\n const format = this.format;\n const definitions = DateTimeFormatter.getTokenDefinitions();\n const tokenPrefix = DateTimeFormatter.TOKEN_PREFIX;\n const occurrence = DateTimeFormatter.findTokens(format);\n const tokenObj = {};\n\n let lastOccurrenceIndex;\n let occObj;\n let occIndex;\n let targetText;\n let regexFormat;\n\n let l;\n let i;\n\n regexFormat = String(format);\n\n const tokenArr = occurrence.map(obj => obj.token);\n const occurrenceLength = occurrence.length;\n for (i = occurrenceLength - 1; i >= 0; i--) {\n occIndex = occurrence[i].index;\n\n if (occIndex + 1 === regexFormat.length - 1) {\n lastOccurrenceIndex = occIndex;\n continue;\n }\n\n if (lastOccurrenceIndex === undefined) {\n lastOccurrenceIndex = regexFormat.length;\n }\n\n targetText = regexFormat.substring(occIndex + 2, lastOccurrenceIndex);\n regexFormat = regexFormat.substring(0, occIndex + 2) +\n RegExp.escape(targetText) +\n regexFormat.substring(lastOccurrenceIndex, regexFormat.length);\n\n lastOccurrenceIndex = occIndex;\n }\n\n for (i = 0; i < occurrenceLength; i++) {\n occObj = occurrence[i];\n regexFormat = regexFormat.replace(tokenPrefix + occObj.token, definitions[occObj.token].extract());\n }\n\n const extractValues = dateTimeStamp.match(new RegExp(regexFormat)) || [];\n extractValues.shift();\n\n for (i = 0, l = tokenArr.length; i < l; i++) {\n tokenObj[tokenArr[i]] = extractValues[i];\n }\n return tokenObj;\n};\n\n/*\n * Give back the JS native date formed from user specified date string\n *\n * @return {Date} : Native JS Date\n */\nDateTimeFormatter.prototype.getNativeDate = function (dateTimeStamp) {\n let date = null;\n if (Number.isFinite(dateTimeStamp)) {\n date = new Date(dateTimeStamp);\n } else if (!this.format && Date.parse(dateTimeStamp)) {\n date = new Date(dateTimeStamp);\n }\n else {\n const dtParams = this.dtParams = this.parse(dateTimeStamp);\n if (dtParams.length) {\n this.nativeDate = new Date(...dtParams);\n date = this.nativeDate;\n }\n }\n return date;\n};\n\nDateTimeFormatter.prototype.checkIfOnlyYear = function(len) {\n return len === 1 && this.format.match(/y|Y/g).length;\n};\n\n/*\n * Represents JS native date to a user specified format.\n *\n * @param format {String} : The format according to which the date is to be represented\n * @return {String} : The formatted date string\n */\nDateTimeFormatter.prototype.formatAs = function (format, dateTimeStamp) {\n let nativeDate;\n\n if (dateTimeStamp) {\n nativeDate = this.nativeDate = this.getNativeDate(dateTimeStamp);\n } else if (!(nativeDate = this.nativeDate)) {\n nativeDate = this.getNativeDate(dateTimeStamp);\n }\n\n return DateTimeFormatter.formatAs(nativeDate, format);\n};\n\nexport { DateTimeFormatter as default };\n","/**\n * The utility function to calculate major column.\n *\n * @param {Object} store - The store object.\n * @return {Function} Returns the push function.\n */\nexport default (store) => {\n let i = 0;\n return (...fields) => {\n fields.forEach((val, fieldIndex) => {\n if (!(store[fieldIndex] instanceof Array)) {\n store[fieldIndex] = Array.from({ length: i });\n }\n store[fieldIndex].push(val);\n });\n i++;\n };\n};\n","/* eslint-disable */\nconst OBJECTSTRING = 'object';\nconst objectToStrFn = Object.prototype.toString;\nconst objectToStr = '[object Object]';\nconst arrayToStr = '[object Array]';\n\nfunction checkCyclicRef(obj, parentArr) {\n let i = parentArr.length;\n let bIndex = -1;\n\n while (i) {\n if (obj === parentArr[i]) {\n bIndex = i;\n return bIndex;\n }\n i -= 1;\n }\n\n return bIndex;\n}\n\nfunction merge(obj1, obj2, skipUndef, tgtArr, srcArr) {\n var item,\n srcVal,\n tgtVal,\n str,\n cRef;\n // check whether obj2 is an array\n // if array then iterate through it's index\n // **** MOOTOOLS precution\n\n if (!srcArr) {\n tgtArr = [obj1];\n srcArr = [obj2];\n }\n else {\n tgtArr.push(obj1);\n srcArr.push(obj2);\n }\n\n if (obj2 instanceof Array) {\n for (item = 0; item < obj2.length; item += 1) {\n try {\n srcVal = obj1[item];\n tgtVal = obj2[item];\n }\n catch (e) {\n continue;\n }\n\n if (typeof tgtVal !== OBJECTSTRING) {\n if (!(skipUndef && tgtVal === undefined)) {\n obj1[item] = tgtVal;\n }\n }\n else {\n if (srcVal === null || typeof srcVal !== OBJECTSTRING) {\n srcVal = obj1[item] = tgtVal instanceof Array ? [] : {};\n }\n cRef = checkCyclicRef(tgtVal, srcArr);\n if (cRef !== -1) {\n srcVal = obj1[item] = tgtArr[cRef];\n }\n else {\n merge(srcVal, tgtVal, skipUndef, tgtArr, srcArr);\n }\n }\n }\n }\n else {\n for (item in obj2) {\n try {\n srcVal = obj1[item];\n tgtVal = obj2[item];\n }\n catch (e) {\n continue;\n }\n\n if (tgtVal !== null && typeof tgtVal === OBJECTSTRING) {\n // Fix for issue BUG: FWXT-602\n // IE < 9 Object.prototype.toString.call(null) gives\n // '[object Object]' instead of '[object Null]'\n // that's why null value becomes Object in IE < 9\n str = objectToStrFn.call(tgtVal);\n if (str === objectToStr) {\n if (srcVal === null || typeof srcVal !== OBJECTSTRING) {\n srcVal = obj1[item] = {};\n }\n cRef = checkCyclicRef(tgtVal, srcArr);\n if (cRef !== -1) {\n srcVal = obj1[item] = tgtArr[cRef];\n }\n else {\n merge(srcVal, tgtVal, skipUndef, tgtArr, srcArr);\n }\n }\n else if (str === arrayToStr) {\n if (srcVal === null || !(srcVal instanceof Array)) {\n srcVal = obj1[item] = [];\n }\n cRef = checkCyclicRef(tgtVal, srcArr);\n if (cRef !== -1) {\n srcVal = obj1[item] = tgtArr[cRef];\n }\n else {\n merge(srcVal, tgtVal, skipUndef, tgtArr, srcArr);\n }\n }\n else {\n obj1[item] = tgtVal;\n }\n }\n else {\n if (skipUndef && tgtVal === undefined) {\n continue;\n }\n obj1[item] = tgtVal;\n }\n }\n }\n return obj1;\n}\n\n\nfunction extend2 (obj1, obj2, skipUndef) {\n //if none of the arguments are object then return back\n if (typeof obj1 !== OBJECTSTRING && typeof obj2 !== OBJECTSTRING) {\n return null;\n }\n\n if (typeof obj2 !== OBJECTSTRING || obj2 === null) {\n return obj1;\n }\n\n if (typeof obj1 !== OBJECTSTRING) {\n obj1 = obj2 instanceof Array ? [] : {};\n }\n merge(obj1, obj2, skipUndef);\n return obj1;\n}\n\nexport { extend2 as default };\n","import { DataFormat } from '../enums';\n\n/**\n * Checks whether the value is an array.\n *\n * @param {*} val - The value to be checked.\n * @return {boolean} Returns true if the value is an array otherwise returns false.\n */\nexport function isArray (val) {\n return Array.isArray(val);\n}\n\n/**\n * Checks whether the value is an object.\n *\n * @param {*} val - The value to be checked.\n * @return {boolean} Returns true if the value is an object otherwise returns false.\n */\nexport function isObject (val) {\n return val === Object(val);\n}\n\n/**\n * Checks whether the value is a string value.\n *\n * @param {*} val - The value to be checked.\n * @return {boolean} Returns true if the value is a string value otherwise returns false.\n */\nexport function isString (val) {\n return typeof val === 'string';\n}\n\n/**\n * Checks whether the value is callable.\n *\n * @param {*} val - The value to be checked.\n * @return {boolean} Returns true if the value is callable otherwise returns false.\n */\nexport function isCallable (val) {\n return typeof val === 'function';\n}\n\n/**\n * Returns the unique values from the input array.\n *\n * @param {Array} data - The input array.\n * @return {Array} Returns a new array of unique values.\n */\nexport function uniqueValues (data) {\n return [...new Set(data)];\n}\n\nexport const getUniqueId = () => `id-${new Date().getTime()}${Math.round(Math.random() * 10000)}`;\n\n/**\n * Checks Whether two arrays have same content.\n *\n * @param {Array} arr1 - The first array.\n * @param {Array} arr2 - The 2nd array.\n * @return {boolean} Returns whether two array have same content.\n */\nexport function isArrEqual(arr1, arr2) {\n if (!isArray(arr1) || !isArray(arr2)) {\n return arr1 === arr2;\n }\n\n if (arr1.length !== arr2.length) {\n return false;\n }\n\n for (let i = 0; i < arr1.length; i++) {\n if (arr1[i] !== arr2[i]) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * It is the default number format function for the measure field type.\n *\n * @param {any} val - The input value.\n * @return {number} Returns a number value.\n */\nexport function formatNumber(val) {\n return val;\n}\n\n/**\n * Returns the detected data format.\n *\n * @param {any} data - The input data to be tested.\n * @return {string} Returns the data format name.\n */\nexport const detectDataFormat = (data) => {\n if (isString(data)) {\n return DataFormat.DSV_STR;\n } else if (isArray(data) && isArray(data[0])) {\n return DataFormat.DSV_ARR;\n } else if (isArray(data) && (data.length === 0 || isObject(data[0]))) {\n return DataFormat.FLAT_JSON;\n }\n return null;\n};\n","import { FieldType } from './enums';\nimport { getUniqueId } from './utils';\n\nconst fieldStore = {\n data: {},\n\n createNamespace (fieldArr, name) {\n const dataId = name || getUniqueId();\n\n this.data[dataId] = {\n name: dataId,\n fields: fieldArr,\n\n fieldsObj () {\n let fieldsObj = this._cachedFieldsObj;\n\n if (!fieldsObj) {\n fieldsObj = this._cachedFieldsObj = {};\n this.fields.forEach((field) => {\n fieldsObj[field.name()] = field;\n });\n }\n return fieldsObj;\n },\n getMeasure () {\n let measureFields = this._cachedMeasure;\n\n if (!measureFields) {\n measureFields = this._cachedMeasure = {};\n this.fields.forEach((field) => {\n if (field.schema().type === FieldType.MEASURE) {\n measureFields[field.name()] = field;\n }\n });\n }\n return measureFields;\n },\n getDimension () {\n let dimensionFields = this._cachedDimension;\n\n if (!this._cachedDimension) {\n dimensionFields = this._cachedDimension = {};\n this.fields.forEach((field) => {\n if (field.schema().type === FieldType.DIMENSION) {\n dimensionFields[field.name()] = field;\n }\n });\n }\n return dimensionFields;\n },\n };\n return this.data[dataId];\n },\n};\n\nexport default fieldStore;\n","import { getNumberFormattedVal } from './helper';\n\n/**\n * The wrapper class on top of the primitive value of a field.\n *\n * @todo Need to have support for StringValue, NumberValue, DateTimeValue\n * and GeoValue. These types should expose predicate API mostly.\n */\nclass Value {\n\n /**\n * Creates new Value instance.\n *\n * @param {*} val - the primitive value from the field cell.\n * @param {string | Field} field - The field from which the value belongs.\n */\n constructor (value, rawValue, field) {\n const formattedValue = getNumberFormattedVal(field, value);\n\n Object.defineProperties(this, {\n _value: {\n enumerable: false,\n configurable: false,\n writable: false,\n value\n },\n _formattedValue: {\n enumerable: false,\n configurable: false,\n writable: false,\n value: formattedValue\n },\n _internalValue: {\n enumerable: false,\n configurable: false,\n writable: false,\n value: rawValue\n }\n });\n\n this.field = field;\n }\n\n /**\n * Returns the field value.\n *\n * @return {*} Returns the current value.\n */\n get value () {\n return this._value;\n }\n\n /**\n * Returns the parsed value of field\n */\n get formattedValue () {\n return this._formattedValue;\n }\n\n /**\n * Returns the internal value of field\n */\n get internalValue () {\n return this._internalValue;\n }\n\n /**\n * Converts to human readable string.\n *\n * @override\n * @return {string} Returns a human readable string of the field value.\n *\n */\n toString () {\n return String(this.value);\n }\n\n /**\n * Returns the value of the field.\n *\n * @override\n * @return {*} Returns the field value.\n */\n valueOf () {\n return this.value;\n }\n}\n\nexport default Value;\n","/**\n * Iterates through the diffSet array and call the callback with the current\n * index.\n *\n * @param {string} rowDiffset - The row diffset string e.g. '0-4,6,10-13'.\n * @param {Function} callback - The callback function to be called with every index.\n */\nexport function rowDiffsetIterator (rowDiffset, callback) {\n if (rowDiffset.length > 0) {\n const rowDiffArr = rowDiffset.split(',');\n rowDiffArr.forEach((diffStr) => {\n const diffStsArr = diffStr.split('-');\n const start = +(diffStsArr[0]);\n const end = +(diffStsArr[1] || diffStsArr[0]);\n if (end >= start) {\n for (let i = start; i <= end; i += 1) {\n callback(i);\n }\n }\n });\n }\n}\n","/**\n * A parser to parser null, undefined, invalid and NIL values.\n *\n * @public\n * @class\n */\nclass InvalidAwareTypes {\n /**\n * Static method which gets/sets the invalid value registry.\n *\n * @public\n * @param {Object} config - The custom configuration supplied by user.\n * @return {Object} Returns the invalid values registry.\n */\n static invalidAwareVals (config) {\n if (!config) {\n return InvalidAwareTypes._invalidAwareValsMap;\n }\n return Object.assign(InvalidAwareTypes._invalidAwareValsMap, config);\n }\n\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {string} value - The value of the invalid data type.\n */\n constructor (value) {\n this._value = value;\n }\n\n /**\n * Returns the current value of the instance.\n *\n * @public\n * @return {string} Returns the value of the invalid data type.\n */\n value () {\n return this._value;\n }\n\n /**\n * Returns the current value of the instance in string format.\n *\n * @public\n * @return {string} Returns the value of the invalid data type.\n */\n toString () {\n return String(this._value);\n }\n\n static isInvalid(val) {\n return (val instanceof InvalidAwareTypes) || !!InvalidAwareTypes.invalidAwareVals()[val];\n }\n\n static getInvalidType(val) {\n return val instanceof InvalidAwareTypes ? val : InvalidAwareTypes.invalidAwareVals()[val];\n }\n}\n\n/**\n * Enums for Invalid types.\n */\nInvalidAwareTypes.NULL = new InvalidAwareTypes('null');\nInvalidAwareTypes.NA = new InvalidAwareTypes('na');\nInvalidAwareTypes.NIL = new InvalidAwareTypes('nil');\n\n/**\n * Default Registry for mapping the invalid values.\n *\n * @private\n */\nInvalidAwareTypes._invalidAwareValsMap = {\n invalid: InvalidAwareTypes.NA,\n nil: InvalidAwareTypes.NIL,\n null: InvalidAwareTypes.NULL,\n undefined: InvalidAwareTypes.NA\n};\n\nexport default InvalidAwareTypes;\n","import { rowDiffsetIterator } from './row-diffset-iterator';\nimport InvalidAwareTypes from '../invalid-aware-types';\n\nconst generateBuckets = (binSize, start, end) => {\n const buckets = [];\n let next = start;\n\n while (next < end) {\n buckets.push(next);\n next += binSize;\n }\n buckets.push(next);\n\n return buckets;\n};\n\nconst findBucketRange = (bucketRanges, value) => {\n let leftIdx = 0;\n let rightIdx = bucketRanges.length - 1;\n let midIdx;\n let range;\n\n // Here use binary search as the bucketRanges is a sorted array\n while (leftIdx <= rightIdx) {\n midIdx = leftIdx + Math.floor((rightIdx - leftIdx) / 2);\n range = bucketRanges[midIdx];\n\n if (value >= range.start && value < range.end) {\n return range;\n } else if (value >= range.end) {\n leftIdx = midIdx + 1;\n } else if (value < range.start) {\n rightIdx = midIdx - 1;\n }\n }\n\n return null;\n};\n\n /**\n * Creates the bin data from input measure field and supplied configs.\n *\n * @param {Measure} measureField - The Measure field instance.\n * @param {string} rowDiffset - The datamodel rowDiffset values.\n * @param {Object} config - The config object.\n * @return {Object} Returns the binned data and the corresponding bins.\n */\nexport function createBinnedFieldData (measureField, rowDiffset, config) {\n let { buckets, binsCount, binSize, start, end } = config;\n const [dMin, dMax] = measureField.domain();\n\n if (!buckets) {\n start = (start !== 0 && (!start || start > dMin)) ? dMin : start;\n end = (end !== 0 && (!end || end < dMax)) ? (dMax + 1) : end;\n\n if (binsCount) {\n binSize = Math.ceil(Math.abs(end - start) / binsCount);\n }\n\n buckets = generateBuckets(binSize, start, end);\n }\n\n if (buckets[0] > dMin) {\n buckets.unshift(dMin);\n }\n if (buckets[buckets.length - 1] <= dMax) {\n buckets.push(dMax + 1);\n }\n\n const bucketRanges = [];\n for (let i = 0; i < buckets.length - 1; i++) {\n bucketRanges.push({\n start: buckets[i],\n end: buckets[i + 1]\n });\n }\n\n const binnedData = [];\n rowDiffsetIterator(rowDiffset, (i) => {\n const datum = measureField.partialField.data[i];\n if (datum instanceof InvalidAwareTypes) {\n binnedData.push(datum);\n return;\n }\n\n const range = findBucketRange(bucketRanges, datum);\n binnedData.push(`${range.start}-${range.end}`);\n });\n\n return { binnedData, bins: buckets };\n}\n","export { DataFormat, FilteringMode } from '../enums';\n/**\n * The event name for data propagation.\n */\nexport const PROPAGATION = 'propagation';\n\n/**\n * The name of the unique row id column in DataModel.\n */\nexport const ROW_ID = '__id__';\n\n/**\n * The enums for operation names performed on DataModel.\n */\nexport const DM_DERIVATIVES = {\n SELECT: 'select',\n PROJECT: 'project',\n GROUPBY: 'group',\n COMPOSE: 'compose',\n CAL_VAR: 'calculatedVariable',\n BIN: 'bin',\n SORT: 'sort'\n};\n\nexport const JOINS = {\n CROSS: 'cross',\n LEFTOUTER: 'leftOuter',\n RIGHTOUTER: 'rightOuter',\n NATURAL: 'natural',\n FULLOUTER: 'fullOuter'\n};\n\nexport const LOGICAL_OPERATORS = {\n AND: 'and',\n OR: 'or'\n};\n","/**\n * The helper function that returns an array of common schema\n * from two fieldStore instances.\n *\n * @param {FieldStore} fs1 - The first FieldStore instance.\n * @param {FieldStore} fs2 - The second FieldStore instance.\n * @return {Array} An array containing the common schema.\n */\nexport function getCommonSchema (fs1, fs2) {\n const retArr = [];\n const fs1Arr = [];\n fs1.fields.forEach((field) => {\n fs1Arr.push(field.schema().name);\n });\n fs2.fields.forEach((field) => {\n if (fs1Arr.indexOf(field.schema().name) !== -1) {\n retArr.push(field.schema().name);\n }\n });\n return retArr;\n}\n","import DataModel from '../datamodel';\nimport { extend2 } from '../utils';\nimport { getCommonSchema } from './get-common-schema';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport { JOINS } from '../constants';\nimport { prepareJoinData } from '../helper';\n/**\n * Default filter function for crossProduct.\n *\n * @return {boolean} Always returns true.\n */\nfunction defaultFilterFn() { return true; }\n\n/**\n * Implementation of cross product operation between two DataModel instances.\n * It internally creates the data and schema for the new DataModel.\n *\n * @param {DataModel} dataModel1 - The left DataModel instance.\n * @param {DataModel} dataModel2 - The right DataModel instance.\n * @param {Function} filterFn - The filter function which is used to filter the tuples.\n * @param {boolean} [replaceCommonSchema=false] - The flag if the common name schema should be there.\n * @return {DataModel} Returns The newly created DataModel instance from the crossProduct operation.\n */\nexport function crossProduct (dm1, dm2, filterFn, replaceCommonSchema = false, jointype = JOINS.CROSS) {\n const schema = [];\n const data = [];\n const applicableFilterFn = filterFn || defaultFilterFn;\n const dm1FieldStore = dm1.getFieldspace();\n const dm2FieldStore = dm2.getFieldspace();\n const dm1FieldStoreName = dm1FieldStore.name;\n const dm2FieldStoreName = dm2FieldStore.name;\n const name = `${dm1FieldStore.name}.${dm2FieldStore.name}`;\n const commonSchemaList = getCommonSchema(dm1FieldStore, dm2FieldStore);\n\n if (dm1FieldStoreName === dm2FieldStoreName) {\n throw new Error('DataModels must have different alias names');\n }\n // Here prepare the schema\n dm1FieldStore.fields.forEach((field) => {\n const tmpSchema = extend2({}, field.schema());\n if (commonSchemaList.indexOf(tmpSchema.name) !== -1 && !replaceCommonSchema) {\n tmpSchema.name = `${dm1FieldStore.name}.${tmpSchema.name}`;\n }\n schema.push(tmpSchema);\n });\n dm2FieldStore.fields.forEach((field) => {\n const tmpSchema = extend2({}, field.schema());\n if (commonSchemaList.indexOf(tmpSchema.name) !== -1) {\n if (!replaceCommonSchema) {\n tmpSchema.name = `${dm2FieldStore.name}.${tmpSchema.name}`;\n schema.push(tmpSchema);\n }\n } else {\n schema.push(tmpSchema);\n }\n });\n\n // Here prepare Data\n rowDiffsetIterator(dm1._rowDiffset, (i) => {\n let rowAdded = false;\n let rowPosition;\n rowDiffsetIterator(dm2._rowDiffset, (ii) => {\n const tuple = [];\n const userArg = {};\n userArg[dm1FieldStoreName] = {};\n userArg[dm2FieldStoreName] = {};\n dm1FieldStore.fields.forEach((field) => {\n tuple.push(field.partialField.data[i]);\n userArg[dm1FieldStoreName][field.name()] = {\n rawValue: field.partialField.data[i],\n formattedValue: field.formattedData()[i],\n };\n });\n dm2FieldStore.fields.forEach((field) => {\n if (!(commonSchemaList.indexOf(field.schema().name) !== -1 && replaceCommonSchema)) {\n tuple.push(field.partialField.data[ii]);\n }\n userArg[dm2FieldStoreName][field.name()] = {\n rawValue: field.partialField.data[ii],\n formattedValue: field.formattedData()[ii],\n };\n });\n\n let cachedStore = {};\n let cloneProvider1 = () => dm1.detachedRoot();\n let cloneProvider2 = () => dm2.detachedRoot();\n\n const dm1Fields = prepareJoinData(userArg[dm1FieldStoreName]);\n const dm2Fields = prepareJoinData(userArg[dm2FieldStoreName]);\n if (applicableFilterFn(dm1Fields, dm2Fields, cloneProvider1, cloneProvider2, cachedStore)) {\n const tupleObj = {};\n tuple.forEach((cellVal, iii) => {\n tupleObj[schema[iii].name] = cellVal;\n });\n if (rowAdded && JOINS.CROSS !== jointype) {\n data[rowPosition] = tupleObj;\n }\n else {\n data.push(tupleObj);\n rowAdded = true;\n rowPosition = i;\n }\n } else if ((jointype === JOINS.LEFTOUTER || jointype === JOINS.RIGHTOUTER) && !rowAdded) {\n const tupleObj = {};\n let len = dm1FieldStore.fields.length - 1;\n tuple.forEach((cellVal, iii) => {\n if (iii <= len) {\n tupleObj[schema[iii].name] = cellVal;\n }\n else {\n tupleObj[schema[iii].name] = null;\n }\n });\n rowAdded = true;\n rowPosition = i;\n data.push(tupleObj);\n }\n });\n });\n\n return new DataModel(data, schema, { name });\n}\n","/**\n * The default sort function.\n *\n * @param {*} a - The first value.\n * @param {*} b - The second value.\n * @return {number} Returns the comparison result e.g. 1 or 0 or -1.\n */\nfunction defSortFn (a, b) {\n const a1 = `${a}`;\n const b1 = `${b}`;\n if (a1 < b1) {\n return -1;\n }\n if (a1 > b1) {\n return 1;\n }\n return 0;\n}\n\n/**\n * The helper function for merge sort which creates the sorted array\n * from the two halves of the input array.\n *\n * @param {Array} arr - The target array which needs to be merged.\n * @param {number} lo - The starting index of the first array half.\n * @param {number} mid - The ending index of the first array half.\n * @param {number} hi - The ending index of the second array half.\n * @param {Function} sortFn - The sort function.\n */\nfunction merge (arr, lo, mid, hi, sortFn) {\n const mainArr = arr;\n const auxArr = [];\n for (let i = lo; i <= hi; i += 1) {\n auxArr[i] = mainArr[i];\n }\n let a = lo;\n let b = mid + 1;\n\n for (let i = lo; i <= hi; i += 1) {\n if (a > mid) {\n mainArr[i] = auxArr[b];\n b += 1;\n } else if (b > hi) {\n mainArr[i] = auxArr[a];\n a += 1;\n } else if (sortFn(auxArr[a], auxArr[b]) <= 0) {\n mainArr[i] = auxArr[a];\n a += 1;\n } else {\n mainArr[i] = auxArr[b];\n b += 1;\n }\n }\n}\n\n/**\n * The helper function for merge sort which would be called\n * recursively for sorting the array halves.\n *\n * @param {Array} arr - The target array which needs to be sorted.\n * @param {number} lo - The starting index of the array half.\n * @param {number} hi - The ending index of the array half.\n * @param {Function} sortFn - The sort function.\n * @return {Array} Returns the target array itself.\n */\nfunction sort (arr, lo, hi, sortFn) {\n if (hi === lo) { return arr; }\n\n const mid = lo + Math.floor((hi - lo) / 2);\n sort(arr, lo, mid, sortFn);\n sort(arr, mid + 1, hi, sortFn);\n merge(arr, lo, mid, hi, sortFn);\n\n return arr;\n}\n\n/**\n * The implementation of merge sort.\n * It is used in DataModel for stable sorting as it is not sure\n * what the sorting algorithm used by browsers is stable or not.\n *\n * @param {Array} arr - The target array which needs to be sorted.\n * @param {Function} [sortFn=defSortFn] - The sort function.\n * @return {Array} Returns the input array itself in sorted order.\n */\nexport function mergeSort (arr, sortFn = defSortFn) {\n if (arr.length > 1) {\n sort(arr, 0, arr.length - 1, sortFn);\n }\n return arr;\n}\n","import { DimensionSubtype, MeasureSubtype } from '../enums';\nimport { mergeSort } from './merge-sort';\nimport { fieldInSchema } from '../helper';\nimport { isCallable, isArray } from '../utils';\n\n/**\n * Generates the sorting functions to sort the data of a DataModel instance\n * according to the input data type.\n *\n * @param {string} dataType - The data type e.g. 'measure', 'datetime' etc.\n * @param {string} sortType - The sorting order i.e. 'asc' or 'desc'.\n * @return {Function} Returns the the sorting function.\n */\nfunction getSortFn (dataType, sortType) {\n let retFunc;\n\n switch (dataType) {\n case MeasureSubtype.CONTINUOUS:\n case DimensionSubtype.TEMPORAL:\n if (sortType === 'asc') {\n retFunc = (a, b) => a - b;\n } else {\n retFunc = (a, b) => b - a;\n }\n break;\n default:\n if (sortType === 'asc') {\n retFunc = (a, b) => {\n a = `${a}`;\n b = `${b}`;\n if (a === b) {\n return 0;\n }\n return a > b ? 1 : -1;\n };\n } else {\n retFunc = (a, b) => {\n a = `${a}`;\n b = `${b}`;\n if (a === b) {\n return 0;\n }\n return a > b ? -1 : 1;\n };\n }\n }\n\n return retFunc;\n}\n\n/**\n * Resolves the actual sorting function based on sorting string value.\n *\n * @param {Object} fDetails - The target field info.\n * @param {string} strSortOrder - The sort order value.\n * @return {Function} Returns the sorting function.\n */\nfunction resolveStrSortOrder (fDetails, strSortOrder) {\n const sortOrder = String(strSortOrder).toLowerCase() === 'desc' ? 'desc' : 'asc';\n return getSortFn(fDetails.type, sortOrder);\n}\n\n/**\n * Groups the data according to the specified target field.\n *\n * @param {Array} data - The input data array.\n * @param {number} fieldIndex - The target field index within schema array.\n * @return {Array} Returns an array containing the grouped data.\n */\nfunction groupData (data, fieldIndex) {\n const hashMap = new Map();\n const groupedData = [];\n\n data.forEach((datum) => {\n const fieldVal = datum[fieldIndex];\n if (hashMap.has(fieldVal)) {\n groupedData[hashMap.get(fieldVal)][1].push(datum);\n } else {\n groupedData.push([fieldVal, [datum]]);\n hashMap.set(fieldVal, groupedData.length - 1);\n }\n });\n\n return groupedData;\n}\n\n/**\n * Creates the argument value used for sorting function when sort is done\n * with another fields.\n *\n * @param {Array} groupedDatum - The grouped datum for a single dimension field value.\n * @param {Array} targetFields - An array of the sorting fields.\n * @param {Array} targetFieldDetails - An array of the sorting field details in schema.\n * @return {Object} Returns an object containing the value of sorting fields and the target field name.\n */\nfunction createSortingFnArg (groupedDatum, targetFields, targetFieldDetails) {\n const arg = {\n label: groupedDatum[0]\n };\n\n targetFields.reduce((acc, next, idx) => {\n acc[next] = groupedDatum[1].map(datum => datum[targetFieldDetails[idx].index]);\n return acc;\n }, arg);\n\n return arg;\n}\n\n/**\n * Sorts the data by applying the standard sorting mechanism.\n *\n * @param {Array} data - The input data array.\n * @param {Array} schema - The data schema.\n * @param {Array} sortingDetails - An array containing the sorting configs.\n */\nfunction applyStandardSort (data, schema, sortingDetails) {\n let fieldName;\n let sortMeta;\n let fDetails;\n let i = sortingDetails.length - 1;\n\n for (; i >= 0; i--) {\n fieldName = sortingDetails[i][0];\n sortMeta = sortingDetails[i][1];\n fDetails = fieldInSchema(schema, fieldName);\n\n if (!fDetails) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n if (isCallable(sortMeta)) {\n // eslint-disable-next-line no-loop-func\n mergeSort(data, (a, b) => sortMeta(a[fDetails.index], b[fDetails.index]));\n } else if (isArray(sortMeta)) {\n const groupedData = groupData(data, fDetails.index);\n const sortingFn = sortMeta[sortMeta.length - 1];\n const targetFields = sortMeta.slice(0, sortMeta.length - 1);\n const targetFieldDetails = targetFields.map(f => fieldInSchema(schema, f));\n\n groupedData.forEach((groupedDatum) => {\n groupedDatum.push(createSortingFnArg(groupedDatum, targetFields, targetFieldDetails));\n });\n\n mergeSort(groupedData, (a, b) => {\n const m = a[2];\n const n = b[2];\n return sortingFn(m, n);\n });\n\n // Empty the array\n data.length = 0;\n groupedData.forEach((datum) => {\n data.push(...datum[1]);\n });\n } else {\n const sortFn = resolveStrSortOrder(fDetails, sortMeta);\n // eslint-disable-next-line no-loop-func\n mergeSort(data, (a, b) => sortFn(a[fDetails.index], b[fDetails.index]));\n }\n }\n}\n\n/**\n * Creates a map based on grouping.\n *\n * @param {Array} depColumns - The dependency columns' info.\n * @param {Array} data - The input data.\n * @param {Array} schema - The data schema.\n * @param {Array} sortingDetails - The sorting details for standard sorting.\n * @return {Map} Returns a map.\n */\nconst makeGroupMapAndSort = (depColumns, data, schema, sortingDetails) => {\n if (depColumns.length === 0) { return data; }\n\n const targetCol = depColumns[0];\n const map = new Map();\n\n data.reduce((acc, currRow) => {\n const fVal = currRow[targetCol.index];\n if (acc.has(fVal)) {\n acc.get(fVal).push(currRow);\n } else {\n acc.set(fVal, [currRow]);\n }\n return acc;\n }, map);\n\n for (let [key, val] of map) {\n const nMap = makeGroupMapAndSort(depColumns.slice(1), val, schema, sortingDetails);\n map.set(key, nMap);\n if (Array.isArray(nMap)) {\n applyStandardSort(nMap, schema, sortingDetails);\n }\n }\n\n return map;\n};\n\n/**\n * Sorts the data by retaining the position/order of a particular field.\n *\n * @param {Array} data - The input data array.\n * @param {Array} schema - The data schema.\n * @param {Array} sortingDetails - An array containing the sorting configs.\n * @param {Array} depColumns - The dependency column list.\n * @return {Array} Returns the sorted data.\n */\nfunction applyGroupSort (data, schema, sortingDetails, depColumns) {\n sortingDetails = sortingDetails.filter((detail) => {\n if (detail[1] === null) {\n depColumns.push(detail[0]);\n return false;\n }\n return true;\n });\n if (sortingDetails.length === 0) { return data; }\n\n depColumns = depColumns.map(c => fieldInSchema(schema, c));\n\n const sortedGroupMap = makeGroupMapAndSort(depColumns, data, schema, sortingDetails);\n return data.map((row) => {\n let i = 0;\n let nextMap = sortedGroupMap;\n\n while (!Array.isArray(nextMap)) {\n nextMap = nextMap.get(row[depColumns[i++].index]);\n }\n\n return nextMap.shift();\n });\n}\n\n/**\n * Sorts the data.\n *\n * @param {Object} dataObj - An object containing the data and schema.\n * @param {Array} sortingDetails - An array containing the sorting configs.\n */\nexport function sortData (dataObj, sortingDetails) {\n let { schema, data } = dataObj;\n\n sortingDetails = sortingDetails.filter(sDetial => !!fieldInSchema(schema, sDetial[0]));\n if (sortingDetails.length === 0) { return; }\n\n let groupSortingIdx = sortingDetails.findIndex(sDetial => sDetial[1] === null);\n groupSortingIdx = groupSortingIdx !== -1 ? groupSortingIdx : sortingDetails.length;\n\n const standardSortingDetails = sortingDetails.slice(0, groupSortingIdx);\n const groupSortingDetails = sortingDetails.slice(groupSortingIdx);\n\n applyStandardSort(data, schema, standardSortingDetails);\n data = applyGroupSort(data, schema, groupSortingDetails, standardSortingDetails.map(detail => detail[0]));\n\n dataObj.uids = data.map(row => row.pop());\n dataObj.data = data;\n}\n","import { rowDiffsetIterator } from './row-diffset-iterator';\nimport { sortData } from './sort';\n\n/**\n * Builds the actual data array.\n *\n * @param {Array} fieldStore - An array of field.\n * @param {string} rowDiffset - A string consisting of which rows to be included eg. '0-2,4,6';\n * @param {string} colIdentifier - A string consisting of the details of which column\n * to be included eg 'date,sales,profit';\n * @param {Object} sortingDetails - An object containing the sorting details of the DataModel instance.\n * @param {Object} options - The options required to create the type of the data.\n * @return {Object} Returns an object containing the multidimensional array and the relative schema.\n */\nexport function dataBuilder (fieldStore, rowDiffset, colIdentifier, sortingDetails, options) {\n const defOptions = {\n addUid: false,\n columnWise: false\n };\n options = Object.assign({}, defOptions, options);\n\n const retObj = {\n schema: [],\n data: [],\n uids: []\n };\n const addUid = options.addUid;\n const reqSorting = sortingDetails && sortingDetails.length > 0;\n // It stores the fields according to the colIdentifier argument\n const tmpDataArr = [];\n // Stores the fields according to the colIdentifier argument\n const colIArr = colIdentifier.split(',');\n\n colIArr.forEach((colName) => {\n for (let i = 0; i < fieldStore.length; i += 1) {\n if (fieldStore[i].name() === colName) {\n tmpDataArr.push(fieldStore[i]);\n break;\n }\n }\n });\n\n // Inserts the schema to the schema object\n tmpDataArr.forEach((field) => {\n /** @todo Need to use extend2 here otherwise user can overwrite the schema. */\n retObj.schema.push(field.schema());\n });\n\n if (addUid) {\n retObj.schema.push({\n name: 'uid',\n type: 'identifier'\n });\n }\n\n rowDiffsetIterator(rowDiffset, (i) => {\n retObj.data.push([]);\n const insertInd = retObj.data.length - 1;\n let start = 0;\n tmpDataArr.forEach((field, ii) => {\n retObj.data[insertInd][ii + start] = field.partialField.data[i];\n });\n if (addUid) {\n retObj.data[insertInd][tmpDataArr.length] = i;\n }\n // Creates an array of unique identifiers for each row\n retObj.uids.push(i);\n\n // If sorting needed then there is the need to expose the index\n // mapping from the old index to its new index\n if (reqSorting) { retObj.data[insertInd].push(i); }\n });\n\n // Handles the sort functionality\n if (reqSorting) {\n sortData(retObj, sortingDetails);\n }\n\n if (options.columnWise) {\n const tmpData = Array(...Array(retObj.schema.length)).map(() => []);\n retObj.data.forEach((tuple) => {\n tuple.forEach((data, i) => {\n tmpData[i].push(data);\n });\n });\n retObj.data = tmpData;\n }\n\n return retObj;\n}\n","import DataModel from '../datamodel';\nimport { extend2 } from '../utils';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport { isArrEqual } from '../utils/helper';\n\n/**\n * Performs the union operation between two dm instances.\n *\n * @todo Fix the conflicts between union and difference terminology here.\n *\n * @param {dm} dm1 - The first dm instance.\n * @param {dm} dm2 - The second dm instance.\n * @return {dm} Returns the newly created dm after union operation.\n */\nexport function difference (dm1, dm2) {\n const hashTable = {};\n const schema = [];\n const schemaNameArr = [];\n const data = [];\n const dm1FieldStore = dm1.getFieldspace();\n const dm2FieldStore = dm2.getFieldspace();\n const dm1FieldStoreFieldObj = dm1FieldStore.fieldsObj();\n const dm2FieldStoreFieldObj = dm2FieldStore.fieldsObj();\n const name = `${dm1FieldStore.name} union ${dm2FieldStore.name}`;\n\n // For union the columns should match otherwise return a clone of the dm1\n if (!isArrEqual(dm1._colIdentifier.split(',').sort(), dm2._colIdentifier.split(',').sort())) {\n return null;\n }\n\n // Prepare the schema\n (dm1._colIdentifier.split(',')).forEach((fieldName) => {\n const field = dm1FieldStoreFieldObj[fieldName];\n schema.push(extend2({}, field.schema()));\n schemaNameArr.push(field.schema().name);\n });\n\n /**\n * The helper function to create the data.\n *\n * @param {dm} dm - The dm instance for which the data is inserted.\n * @param {Object} fieldsObj - The fieldStore object format.\n * @param {boolean} addData - If true only tuple will be added to the data.\n */\n function prepareDataHelper(dm, fieldsObj, addData) {\n rowDiffsetIterator(dm._rowDiffset, (i) => {\n const tuple = {};\n let hashData = '';\n schemaNameArr.forEach((schemaName) => {\n const value = fieldsObj[schemaName].partialField.data[i];\n hashData += `-${value}`;\n tuple[schemaName] = value;\n });\n if (!hashTable[hashData]) {\n if (addData) { data.push(tuple); }\n hashTable[hashData] = true;\n }\n });\n }\n\n // Prepare the data\n prepareDataHelper(dm2, dm2FieldStoreFieldObj, false);\n prepareDataHelper(dm1, dm1FieldStoreFieldObj, true);\n\n return new DataModel(data, schema, { name });\n}\n\n","import { isArray } from '../utils';\nimport InvalidAwareTypes from '../invalid-aware-types';\nimport { GROUP_BY_FUNCTIONS } from '../enums';\n\nconst { SUM, AVG, FIRST, LAST, COUNT, STD, MIN, MAX } = GROUP_BY_FUNCTIONS;\n\nfunction getFilteredValues(arr) {\n return arr.filter(item => !(item instanceof InvalidAwareTypes));\n}\n/**\n * Reducer function that returns the sum of all the values.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the sum of the array.\n */\nfunction sum (arr) {\n if (isArray(arr) && !(arr[0] instanceof Array)) {\n const filteredNumber = getFilteredValues(arr);\n const totalSum = filteredNumber.length ?\n filteredNumber.reduce((acc, curr) => acc + curr, 0)\n : InvalidAwareTypes.NULL;\n return totalSum;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Reducer function that returns the average of all the values.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the mean value of the array.\n */\nfunction avg (arr) {\n if (isArray(arr) && !(arr[0] instanceof Array)) {\n const totalSum = sum(arr);\n const len = arr.length || 1;\n return (Number.isNaN(totalSum) || totalSum instanceof InvalidAwareTypes) ?\n InvalidAwareTypes.NULL : totalSum / len;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Reducer function that gives the min value amongst all the values.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the minimum value of the array.\n */\nfunction min (arr) {\n if (isArray(arr) && !(arr[0] instanceof Array)) {\n // Filter out undefined, null and NaN values\n const filteredValues = getFilteredValues(arr);\n\n return (filteredValues.length) ? Math.min(...filteredValues) : InvalidAwareTypes.NULL;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Reducer function that gives the max value amongst all the values.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the maximum value of the array.\n */\nfunction max (arr) {\n if (isArray(arr) && !(arr[0] instanceof Array)) {\n // Filter out undefined, null and NaN values\n const filteredValues = getFilteredValues(arr);\n\n return (filteredValues.length) ? Math.max(...filteredValues) : InvalidAwareTypes.NULL;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Reducer function that gives the first value of the array.\n *\n * @public\n * @param {Array} arr - The input array.\n * @return {number} Returns the first value of the array.\n */\nfunction first (arr) {\n return arr[0];\n}\n\n/**\n * Reducer function that gives the last value of the array.\n *\n * @public\n * @param {Array} arr - The input array.\n * @return {number} Returns the last value of the array.\n */\nfunction last (arr) {\n return arr[arr.length - 1];\n}\n\n/**\n * Reducer function that gives the count value of the array.\n *\n * @public\n * @param {Array} arr - The input array.\n * @return {number} Returns the length of the array.\n */\nfunction count (arr) {\n if (isArray(arr)) {\n return arr.length;\n }\n return InvalidAwareTypes.NULL;\n}\n\n/**\n * Calculates the variance of the input array.\n *\n * @param {Array.} arr - The input array.\n * @return {number} Returns the variance of the input array.\n */\nfunction variance (arr) {\n let mean = avg(arr);\n return avg(arr.map(num => (num - mean) ** 2));\n}\n\n/**\n * Calculates the square root of the variance of the input array.\n *\n * @public\n * @param {Array.} arr - The input array.\n * @return {number} Returns the square root of the variance.\n */\nfunction std (arr) {\n return Math.sqrt(variance(arr));\n}\n\n\nconst fnList = {\n [SUM]: sum,\n [AVG]: avg,\n [MIN]: min,\n [MAX]: max,\n [FIRST]: first,\n [LAST]: last,\n [COUNT]: count,\n [STD]: std\n};\n\nconst defaultReducerName = SUM;\n\nexport {\n defaultReducerName,\n sum as defReducer,\n fnList,\n};\n","import { defReducer, fnList } from '../operator';\n\n/**\n * A page level storage which stores, registers, unregisters reducers for all the datamodel instances. There is only one\n * reducer store available in a page. All the datamodel instances receive same instance of reducer store. DataModel\n * out of the box provides handful of {@link reducer | reducers} which can be used as reducer funciton.\n *\n * @public\n * @namespace DataModel\n */\nclass ReducerStore {\n constructor () {\n this.store = new Map();\n this.store.set('defReducer', defReducer);\n\n Object.entries(fnList).forEach((key) => {\n this.store.set(key[0], key[1]);\n });\n }\n\n /**\n * Changes the `defaultReducer` globally. For all the fields which does not have `defAggFn` mentioned in schema, the\n * value of `defaultReducer` is used for aggregation.\n *\n * @public\n * @param {string} [reducer='sum'] - The name of the default reducer. It picks up the definition from store by doing\n * name lookup. If no name is found then it takes `sum` as the default reducer.\n * @return {ReducerStore} Returns instance of the singleton store in page.\n */\n defaultReducer (...params) {\n if (!params.length) {\n return this.store.get('defReducer');\n }\n\n let reducer = params[0];\n\n if (typeof reducer === 'function') {\n this.store.set('defReducer', reducer);\n } else {\n reducer = String(reducer);\n if (Object.keys(fnList).indexOf(reducer) !== -1) {\n this.store.set('defReducer', fnList[reducer]);\n } else {\n throw new Error(`Reducer ${reducer} not found in registry`);\n }\n }\n return this;\n }\n\n /**\n *\n * Registers a {@link reducer | reducer}.\n * A {@link reducer | reducer} has to be registered before it is used.\n *\n * @example\n * // find the mean squared value of a given set\n * const reducerStore = DataModel.Reducers();\n *\n * reducers.register('meanSquared', (arr) => {\n * const squaredVal = arr.map(item => item * item);\n * let sum = 0;\n * for (let i = 0, l = squaredVal.length; i < l; i++) {\n * sum += squaredVal[i++];\n * }\n *\n * return sum;\n * })\n *\n * // datamodel (dm) is already prepared with cars.json\n * const dm1 = dm.groupBy(['origin'], {\n * accleration: 'meanSquared'\n * });\n *\n * @public\n *\n * @param {string} name formal name for a reducer. If the given name already exists in store it is overridden by new\n * definition.\n * @param {Function} reducer definition of {@link reducer} function.\n *\n * @return {Function} function for unregistering the reducer.\n */\n register (name, reducer) {\n if (typeof reducer !== 'function') {\n throw new Error('Reducer should be a function');\n }\n\n name = String(name);\n this.store.set(name, reducer);\n\n return () => { this.__unregister(name); };\n }\n\n __unregister (name) {\n if (this.store.has(name)) {\n this.store.delete(name);\n }\n }\n\n resolve (name) {\n if (name instanceof Function) {\n return name;\n }\n return this.store.get(name);\n }\n}\n\nconst reducerStore = (function () {\n let store = null;\n\n function getStore () {\n if (store === null) {\n store = new ReducerStore();\n }\n return store;\n }\n return getStore();\n}());\n\nexport default reducerStore;\n","import { extend2 } from '../utils';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport DataModel from '../export';\nimport reducerStore from '../utils/reducer-store';\nimport { defaultReducerName } from './group-by-function';\nimport { FieldType } from '../enums';\n\n/**\n * This function sanitize the user given field and return a common Array structure field\n * list\n * @param {DataModel} dataModel the dataModel operating on\n * @param {Array} fieldArr user input of field Array\n * @return {Array} arrays of field name\n */\nfunction getFieldArr (dataModel, fieldArr) {\n const retArr = [];\n const fieldStore = dataModel.getFieldspace();\n const dimensions = fieldStore.getDimension();\n\n Object.entries(dimensions).forEach(([key]) => {\n if (fieldArr && fieldArr.length) {\n if (fieldArr.indexOf(key) !== -1) {\n retArr.push(key);\n }\n } else {\n retArr.push(key);\n }\n });\n\n return retArr;\n}\n\n/**\n * This sanitize the reducer provide by the user and create a common type of object.\n * user can give function Also\n * @param {DataModel} dataModel dataModel to worked on\n * @param {Object|function} [reducers={}] reducer provided by the users\n * @return {Object} object containing reducer function for every measure\n */\nfunction getReducerObj (dataModel, reducers = {}) {\n const retObj = {};\n const fieldStore = dataModel.getFieldspace();\n const measures = fieldStore.getMeasure();\n const defReducer = reducerStore.defaultReducer();\n\n Object.keys(measures).forEach((measureName) => {\n if (typeof reducers[measureName] !== 'string') {\n reducers[measureName] = measures[measureName].defAggFn();\n }\n const reducerFn = reducerStore.resolve(reducers[measureName]);\n if (reducerFn) {\n retObj[measureName] = reducerFn;\n } else {\n retObj[measureName] = defReducer;\n reducers[measureName] = defaultReducerName;\n }\n });\n return retObj;\n}\n\n/**\n * main function which perform the group-by operations which reduce the measures value is the\n * fields are common according to the reducer function provided\n * @param {DataModel} dataModel the dataModel to worked\n * @param {Array} fieldArr fields according to which the groupby should be worked\n * @param {Object|Function} reducers reducers function\n * @param {DataModel} existingDataModel Existing datamodel instance\n * @return {DataModel} new dataModel with the group by\n */\nfunction groupBy (dataModel, fieldArr, reducers, existingDataModel) {\n const sFieldArr = getFieldArr(dataModel, fieldArr);\n const reducerObj = getReducerObj(dataModel, reducers);\n const fieldStore = dataModel.getFieldspace();\n const fieldStoreObj = fieldStore.fieldsObj();\n const dbName = fieldStore.name;\n const dimensionArr = [];\n const measureArr = [];\n const schema = [];\n const hashMap = {};\n const data = [];\n let newDataModel;\n\n // Prepare the schema\n Object.entries(fieldStoreObj).forEach(([key, value]) => {\n if (sFieldArr.indexOf(key) !== -1 || reducerObj[key]) {\n schema.push(extend2({}, value.schema()));\n\n switch (value.schema().type) {\n case FieldType.MEASURE:\n measureArr.push(key);\n break;\n default:\n case FieldType.DIMENSION:\n dimensionArr.push(key);\n }\n }\n });\n // Prepare the data\n let rowCount = 0;\n rowDiffsetIterator(dataModel._rowDiffset, (i) => {\n let hash = '';\n dimensionArr.forEach((_) => {\n hash = `${hash}-${fieldStoreObj[_].partialField.data[i]}`;\n });\n if (hashMap[hash] === undefined) {\n hashMap[hash] = rowCount;\n data.push({});\n dimensionArr.forEach((_) => {\n data[rowCount][_] = fieldStoreObj[_].partialField.data[i];\n });\n measureArr.forEach((_) => {\n data[rowCount][_] = [fieldStoreObj[_].partialField.data[i]];\n });\n rowCount += 1;\n } else {\n measureArr.forEach((_) => {\n data[hashMap[hash]][_].push(fieldStoreObj[_].partialField.data[i]);\n });\n }\n });\n\n // reduction\n let cachedStore = {};\n let cloneProvider = () => dataModel.detachedRoot();\n data.forEach((row) => {\n const tuple = row;\n measureArr.forEach((_) => {\n tuple[_] = reducerObj[_](row[_], cloneProvider, cachedStore);\n });\n });\n if (existingDataModel) {\n existingDataModel.__calculateFieldspace();\n newDataModel = existingDataModel;\n }\n else {\n newDataModel = new DataModel(data, schema, { name: dbName });\n }\n return newDataModel;\n}\n\nexport { groupBy, getFieldArr, getReducerObj };\n","import { getCommonSchema } from './get-common-schema';\n\n/**\n * The filter function used in natural join.\n * It generates a function that will have the logic to join two\n * DataModel instances by the process of natural join.\n *\n * @param {DataModel} dm1 - The left DataModel instance.\n * @param {DataModel} dm2 - The right DataModel instance.\n * @return {Function} Returns a function that is used in cross-product operation.\n */\nexport function naturalJoinFilter (dm1, dm2) {\n const dm1FieldStore = dm1.getFieldspace();\n const dm2FieldStore = dm2.getFieldspace();\n // const dm1FieldStoreName = dm1FieldStore.name;\n // const dm2FieldStoreName = dm2FieldStore.name;\n const commonSchemaArr = getCommonSchema(dm1FieldStore, dm2FieldStore);\n\n return (dm1Fields, dm2Fields) => {\n let retainTuple = true;\n commonSchemaArr.forEach((fieldName) => {\n if (dm1Fields[fieldName].internalValue ===\n dm2Fields[fieldName].internalValue && retainTuple) {\n retainTuple = true;\n } else {\n retainTuple = false;\n }\n });\n return retainTuple;\n };\n}\n","import DataModel from '../export';\nimport { extend2 } from '../utils';\nimport { rowDiffsetIterator } from './row-diffset-iterator';\nimport { isArrEqual } from '../utils/helper';\n/**\n * Performs the union operation between two dm instances.\n *\n * @param {dm} dm1 - The first dm instance.\n * @param {dm} dm2 - The second dm instance.\n * @return {dm} Returns the newly created dm after union operation.\n */\nexport function union (dm1, dm2) {\n const hashTable = {};\n const schema = [];\n const schemaNameArr = [];\n const data = [];\n const dm1FieldStore = dm1.getFieldspace();\n const dm2FieldStore = dm2.getFieldspace();\n const dm1FieldStoreFieldObj = dm1FieldStore.fieldsObj();\n const dm2FieldStoreFieldObj = dm2FieldStore.fieldsObj();\n const name = `${dm1FieldStore.name} union ${dm2FieldStore.name}`;\n\n // For union the columns should match otherwise return a clone of the dm1\n if (!isArrEqual(dm1._colIdentifier.split(',').sort(), dm2._colIdentifier.split(',').sort())) {\n return null;\n }\n\n // Prepare the schema\n (dm1._colIdentifier.split(',')).forEach((fieldName) => {\n const field = dm1FieldStoreFieldObj[fieldName];\n schema.push(extend2({}, field.schema()));\n schemaNameArr.push(field.schema().name);\n });\n\n /**\n * The helper function to create the data.\n *\n * @param {dm} dm - The dm instance for which the data is inserted.\n * @param {Object} fieldsObj - The fieldStore object format.\n */\n function prepareDataHelper (dm, fieldsObj) {\n rowDiffsetIterator(dm._rowDiffset, (i) => {\n const tuple = {};\n let hashData = '';\n schemaNameArr.forEach((schemaName) => {\n const value = fieldsObj[schemaName].partialField.data[i];\n hashData += `-${value}`;\n tuple[schemaName] = value;\n });\n if (!hashTable[hashData]) {\n data.push(tuple);\n hashTable[hashData] = true;\n }\n });\n }\n\n // Prepare the data\n prepareDataHelper(dm1, dm1FieldStoreFieldObj);\n prepareDataHelper(dm2, dm2FieldStoreFieldObj);\n\n return new DataModel(data, schema, { name });\n}\n","import { crossProduct } from './cross-product';\nimport { JOINS } from '../constants';\nimport { union } from './union';\n\n\nexport function leftOuterJoin (dataModel1, dataModel2, filterFn) {\n return crossProduct(dataModel1, dataModel2, filterFn, false, JOINS.LEFTOUTER);\n}\n\nexport function rightOuterJoin (dataModel1, dataModel2, filterFn) {\n return crossProduct(dataModel2, dataModel1, filterFn, false, JOINS.RIGHTOUTER);\n}\n\nexport function fullOuterJoin (dataModel1, dataModel2, filterFn) {\n return union(leftOuterJoin(dataModel1, dataModel2, filterFn), rightOuterJoin(dataModel1, dataModel2, filterFn));\n}\n","import { rowDiffsetIterator } from '../../operator/row-diffset-iterator';\n\n/**\n * In {@link DataModel}, every tabular data consists of column, a column is stored as field.\n * Field contains all the data for a given column in an array.\n *\n * Each record consists of several fields; the fields of all records form the columns.\n * Examples of fields: name, gender, sex etc.\n *\n * In DataModel, each field can have multiple attributes which describes its data and behaviour.\n * A field can have two types of data: Measure and Dimension.\n *\n * A Dimension Field is the context on which a data is categorized and the measure is the numerical values that\n * quantify the data set.\n * In short a dimension is the lens through which you are looking at your measure data.\n *\n * Refer to {@link Schema} to get info about possible field attributes.\n *\n * @public\n * @class\n */\nexport default class Field {\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {PartialField} partialField - The partialField instance which holds the whole data.\n * @param {string} rowDiffset - The data subset definition.\n */\n constructor (partialField, rowDiffset) {\n this.partialField = partialField;\n this.rowDiffset = rowDiffset;\n }\n\n /**\n * Generates the field type specific domain.\n *\n * @public\n * @abstract\n */\n domain () {\n throw new Error('Not yet implemented');\n }\n\n /**\n * Returns the the field schema.\n *\n * @public\n * @return {string} Returns the field schema.\n */\n schema () {\n return this.partialField.schema;\n }\n\n /**\n * Returns the name of the field.\n *\n * @public\n * @return {string} Returns the name of the field.\n */\n name () {\n return this.partialField.name;\n }\n\n /**\n * Returns the type of the field.\n *\n * @public\n * @return {string} Returns the type of the field.\n */\n type () {\n return this.partialField.schema.type;\n }\n\n /**\n * Returns the subtype of the field.\n *\n * @public\n * @return {string} Returns the subtype of the field.\n */\n subtype () {\n return this.partialField.schema.subtype;\n }\n\n /**\n * Returns the description of the field.\n *\n * @public\n * @return {string} Returns the description of the field.\n */\n description () {\n return this.partialField.schema.description;\n }\n\n /**\n * Returns the display name of the field.\n *\n * @public\n * @return {string} Returns the display name of the field.\n */\n displayName () {\n return this.partialField.schema.displayName || this.partialField.schema.name;\n }\n\n /**\n * Returns the data associated with the field.\n *\n * @public\n * @return {Array} Returns the data.\n */\n data () {\n const data = [];\n rowDiffsetIterator(this.rowDiffset, (i) => {\n data.push(this.partialField.data[i]);\n });\n return data;\n }\n\n /**\n * Returns the formatted version of the underlying field data.\n *\n * @public\n * @abstract\n */\n formattedData () {\n throw new Error('Not yet implemented');\n }\n}\n","import Field from '../field';\n\n/**\n * Represents dimension field type.\n *\n * @public\n * @class\n * @extends Field\n */\nexport default class Dimension extends Field {\n /**\n * Returns the domain for the dimension field.\n *\n * @override\n * @public\n * @return {any} Returns the calculated domain.\n */\n domain () {\n if (!this._cachedDomain) {\n this._cachedDomain = this.calculateDataDomain();\n }\n return this._cachedDomain;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @abstract\n */\n calculateDataDomain () {\n throw new Error('Not yet implemented');\n }\n\n /**\n * Returns the formatted version of the underlying field data.\n *\n * @public\n * @override\n * @return {Array} Returns the formatted data.\n */\n formattedData () {\n return this.data();\n }\n}\n","import { rowDiffsetIterator } from '../../operator/row-diffset-iterator';\nimport { DimensionSubtype } from '../../enums';\nimport Dimension from '../dimension';\n/**\n * Represents categorical field subtype.\n *\n * @public\n * @class\n * @extends Dimension\n */\nexport default class Categorical extends Dimension {\n /**\n * Returns the subtype of the field.\n *\n * @public\n * @override\n * @return {string} Returns the subtype of the field.\n */\n subtype () {\n return DimensionSubtype.CATEGORICAL;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @override\n * @return {Array} Returns the unique values.\n */\n calculateDataDomain () {\n const hash = new Set();\n const domain = [];\n\n // here don't use this.data() as the iteration will be occurred two times on same data.\n rowDiffsetIterator(this.rowDiffset, (i) => {\n const datum = this.partialField.data[i];\n if (!hash.has(datum)) {\n hash.add(datum);\n domain.push(datum);\n }\n });\n return domain;\n }\n}\n","import { rowDiffsetIterator } from '../../operator/row-diffset-iterator';\nimport Dimension from '../dimension';\nimport { DateTimeFormatter } from '../../utils';\nimport InvalidAwareTypes from '../../invalid-aware-types';\n\n/**\n * Represents temporal field subtype.\n *\n * @public\n * @class\n * @extends Dimension\n */\nexport default class Temporal extends Dimension {\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {PartialField} partialField - The partialField instance which holds the whole data.\n * @param {string} rowDiffset - The data subset definition.\n */\n constructor (partialField, rowDiffset) {\n super(partialField, rowDiffset);\n\n this._cachedMinDiff = null;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @override\n * @return {Array} Returns the unique values.\n */\n calculateDataDomain () {\n const hash = new Set();\n const domain = [];\n\n // here don't use this.data() as the iteration will be\n // occurred two times on same data.\n rowDiffsetIterator(this.rowDiffset, (i) => {\n const datum = this.partialField.data[i];\n if (!hash.has(datum)) {\n hash.add(datum);\n domain.push(datum);\n }\n });\n\n return domain;\n }\n\n\n /**\n * Calculates the minimum consecutive difference from the associated field data.\n *\n * @public\n * @return {number} Returns the minimum consecutive diff in milliseconds.\n */\n minimumConsecutiveDifference () {\n if (this._cachedMinDiff) {\n return this._cachedMinDiff;\n }\n\n const sortedData = this.data().filter(item => !(item instanceof InvalidAwareTypes)).sort((a, b) => a - b);\n const arrLn = sortedData.length;\n let minDiff = Number.POSITIVE_INFINITY;\n let prevDatum;\n let nextDatum;\n let processedCount = 0;\n\n for (let i = 1; i < arrLn; i++) {\n prevDatum = sortedData[i - 1];\n nextDatum = sortedData[i];\n\n if (nextDatum === prevDatum) {\n continue;\n }\n\n minDiff = Math.min(minDiff, nextDatum - sortedData[i - 1]);\n processedCount++;\n }\n\n if (!processedCount) {\n minDiff = null;\n }\n this._cachedMinDiff = minDiff;\n\n return this._cachedMinDiff;\n }\n\n /**\n * Returns the format specified in the input schema while creating field.\n *\n * @public\n * @return {string} Returns the datetime format.\n */\n format () {\n return this.partialField.schema.format;\n }\n\n /**\n * Returns the formatted version of the underlying field data\n * If data is of type invalid or has missing format use the raw value\n * @public\n * @override\n * @return {Array} Returns the formatted data.\n */\n formattedData () {\n const data = [];\n const dataFormat = this.format();\n\n rowDiffsetIterator(this.rowDiffset, (i) => {\n const datum = this.partialField.data[i];\n // If value is of invalid type or format is missing\n if (InvalidAwareTypes.isInvalid(datum) || (!dataFormat && Number.isFinite(datum))) {\n // Use the invalid map value or the raw value\n const parsedDatum = InvalidAwareTypes.getInvalidType(datum) || datum;\n data.push(parsedDatum);\n } else {\n data.push(DateTimeFormatter.formatAs(datum, dataFormat));\n }\n });\n return data;\n }\n}\n\n","import Dimension from '../dimension';\n\n/**\n * Represents binned field subtype.\n *\n * @public\n * @class\n * @extends Dimension\n */\nexport default class Binned extends Dimension {\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @override\n * @return {Array} Returns the last and first values of bins config array.\n */\n calculateDataDomain () {\n const binsArr = this.partialField.schema.bins;\n return [binsArr[0], binsArr[binsArr.length - 1]];\n }\n\n /**\n * Returns the bins config provided while creating the field instance.\n *\n * @public\n * @return {Array} Returns the bins array config.\n */\n bins () {\n return this.partialField.schema.bins;\n }\n}\n","import { formatNumber } from '../../utils';\nimport { defaultReducerName } from '../../operator/group-by-function';\nimport Field from '../field';\n\n/**\n * Represents measure field type.\n *\n * @public\n * @class\n * @extends Field\n */\nexport default class Measure extends Field {\n /**\n * Returns the domain for the measure field.\n *\n * @override\n * @public\n * @return {any} Returns the calculated domain.\n */\n domain () {\n if (!this._cachedDomain) {\n this._cachedDomain = this.calculateDataDomain();\n }\n return this._cachedDomain;\n }\n\n /**\n * Returns the unit of the measure field.\n *\n * @public\n * @return {string} Returns unit of the field.\n */\n unit () {\n return this.partialField.schema.unit;\n }\n\n /**\n * Returns the aggregation function name of the measure field.\n *\n * @public\n * @return {string} Returns aggregation function name of the field.\n */\n defAggFn () {\n return this.partialField.schema.defAggFn || defaultReducerName;\n }\n\n /**\n * Returns the number format of the measure field.\n *\n * @public\n * @return {Function} Returns number format of the field.\n */\n numberFormat () {\n const { numberFormat } = this.partialField.schema;\n return numberFormat instanceof Function ? numberFormat : formatNumber;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @abstract\n */\n calculateDataDomain () {\n throw new Error('Not yet implemented');\n }\n\n /**\n * Returns the formatted version of the underlying field data.\n *\n * @public\n * @override\n * @return {Array} Returns the formatted data.\n */\n formattedData () {\n return this.data();\n }\n}\n","import { rowDiffsetIterator } from '../../operator/row-diffset-iterator';\nimport { MeasureSubtype } from '../../enums';\nimport Measure from '../measure';\nimport InvalidAwareTypes from '../../invalid-aware-types';\n\n/**\n * Represents continuous field subtype.\n *\n * @public\n * @class\n * @extends Measure\n */\nexport default class Continuous extends Measure {\n /**\n * Returns the subtype of the field.\n *\n * @public\n * @override\n * @return {string} Returns the subtype of the field.\n */\n subtype () {\n return MeasureSubtype.CONTINUOUS;\n }\n\n /**\n * Calculates the corresponding field domain.\n *\n * @public\n * @override\n * @return {Array} Returns the min and max values.\n */\n calculateDataDomain () {\n let min = Number.POSITIVE_INFINITY;\n let max = Number.NEGATIVE_INFINITY;\n\n // here don't use this.data() as the iteration will be occurred two times on same data.\n rowDiffsetIterator(this.rowDiffset, (i) => {\n const datum = this.partialField.data[i];\n if (datum instanceof InvalidAwareTypes) {\n return;\n }\n\n if (datum < min) {\n min = datum;\n }\n if (datum > max) {\n max = datum;\n }\n });\n\n return [min, max];\n }\n}\n","/**\n * A interface to represent a parser which is responsible to parse the field.\n *\n * @public\n * @interface\n */\nexport default class FieldParser {\n /**\n * Parses a single value of a field and return the sanitized form.\n *\n * @public\n * @abstract\n */\n parse () {\n throw new Error('Not yet implemented');\n }\n}\n","import FieldParser from '../field-parser';\nimport InvalidAwareTypes from '../../../invalid-aware-types';\n\n/**\n * A FieldParser which parses the categorical values.\n *\n * @public\n * @class\n * @implements {FieldParser}\n */\nexport default class CategoricalParser extends FieldParser {\n /**\n * Parses a single value of a field and returns the stringified form.\n *\n * @public\n * @param {string|number} val - The value of the field.\n * @return {string} Returns the stringified value.\n */\n parse (val) {\n let result;\n // check if invalid date value\n if (!InvalidAwareTypes.isInvalid(val)) {\n result = String(val).trim();\n } else {\n result = InvalidAwareTypes.getInvalidType(val);\n }\n return result;\n }\n}\n","import { DateTimeFormatter } from '../../../utils';\nimport FieldParser from '../field-parser';\nimport InvalidAwareTypes from '../../../invalid-aware-types';\n\n/**\n * A FieldParser which parses the temporal values.\n *\n * @public\n * @class\n * @implements {FieldParser}\n */\nexport default class TemporalParser extends FieldParser {\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {Object} schema - The schema object for the corresponding field.\n */\n constructor (schema) {\n super();\n this.schema = schema;\n this._dtf = new DateTimeFormatter(this.schema.format);\n }\n\n /**\n * Parses a single value of a field and returns the millisecond value.\n *\n * @public\n * @param {string|number} val - The value of the field.\n * @return {number} Returns the millisecond value.\n */\n parse (val) {\n let result;\n // check if invalid date value\n if (!InvalidAwareTypes.isInvalid(val)) {\n let nativeDate = this._dtf.getNativeDate(val);\n result = nativeDate ? nativeDate.getTime() : InvalidAwareTypes.NA;\n } else {\n result = InvalidAwareTypes.getInvalidType(val);\n }\n return result;\n }\n}\n","import FieldParser from '../field-parser';\nimport InvalidAwareTypes from '../../../invalid-aware-types';\n\n/**\n * A FieldParser which parses the binned values.\n *\n * @public\n * @class\n * @implements {FieldParser}\n */\nexport default class BinnedParser extends FieldParser {\n /**\n * Parses a single binned value of a field and returns the sanitized value.\n *\n * @public\n * @param {string} val - The value of the field.\n * @return {string} Returns the sanitized value.\n */\n parse (val) {\n const regex = /^\\s*([+-]?\\d+(?:\\.\\d+)?)\\s*-\\s*([+-]?\\d+(?:\\.\\d+)?)\\s*$/;\n val = String(val);\n let result;\n // check if invalid date value\n if (!InvalidAwareTypes.isInvalid(val)) {\n let matched = val.match(regex);\n result = matched ? `${Number.parseFloat(matched[1])}-${Number.parseFloat(matched[2])}`\n : InvalidAwareTypes.NA;\n } else {\n result = InvalidAwareTypes.getInvalidType(val);\n }\n return result;\n }\n}\n","import FieldParser from '../field-parser';\nimport InvalidAwareTypes from '../../../invalid-aware-types';\n\n/**\n * A FieldParser which parses the continuous values.\n *\n * @public\n * @class\n * @implements {FieldParser}\n */\nexport default class ContinuousParser extends FieldParser {\n /**\n * Parses a single value of a field and returns the number form.\n *\n * @public\n * @param {string|number} val - The value of the field.\n * @return {string} Returns the number value.\n */\n parse (val) {\n let result;\n // check if invalid date value\n if (!InvalidAwareTypes.isInvalid(val)) {\n let parsedVal = parseFloat(val, 10);\n result = Number.isNaN(parsedVal) ? InvalidAwareTypes.NA : parsedVal;\n } else {\n result = InvalidAwareTypes.getInvalidType(val);\n }\n return result;\n }\n}\n","/**\n * Stores the full data and the metadata of a field. It provides\n * a single source of data from which the future Field\n * instance can get a subset of it with a rowDiffset config.\n *\n * @class\n * @public\n */\nexport default class PartialField {\n /**\n * Initialize a new instance.\n *\n * @public\n * @param {string} name - The name of the field.\n * @param {Array} data - The data array.\n * @param {Object} schema - The schema object of the corresponding field.\n * @param {FieldParser} parser - The parser instance corresponding to that field.\n */\n constructor (name, data, schema, parser) {\n this.name = name;\n this.schema = schema;\n this.parser = parser;\n this.data = this._sanitize(data);\n }\n\n /**\n * Sanitizes the field data.\n *\n * @private\n * @param {Array} data - The actual input data.\n * @return {Array} Returns the sanitized data.\n */\n _sanitize (data) {\n return data.map(datum => this.parser.parse(datum));\n }\n}\n","import { FieldType, DimensionSubtype, MeasureSubtype } from './enums';\nimport {\n Categorical,\n Temporal,\n Binned,\n Continuous,\n CategoricalParser,\n TemporalParser,\n BinnedParser,\n ContinuousParser,\n PartialField\n} from './fields';\n\n/**\n * Creates a field instance according to the provided data and schema.\n *\n * @param {Array} data - The field data array.\n * @param {Object} schema - The field schema object.\n * @return {Field} Returns the newly created field instance.\n */\nfunction createUnitField(data, schema) {\n data = data || [];\n let partialField;\n\n switch (schema.type) {\n case FieldType.MEASURE:\n switch (schema.subtype) {\n case MeasureSubtype.CONTINUOUS:\n partialField = new PartialField(schema.name, data, schema, new ContinuousParser());\n return new Continuous(partialField, `0-${data.length - 1}`);\n default:\n partialField = new PartialField(schema.name, data, schema, new ContinuousParser());\n return new Continuous(partialField, `0-${data.length - 1}`);\n }\n case FieldType.DIMENSION:\n switch (schema.subtype) {\n case DimensionSubtype.CATEGORICAL:\n partialField = new PartialField(schema.name, data, schema, new CategoricalParser());\n return new Categorical(partialField, `0-${data.length - 1}`);\n case DimensionSubtype.TEMPORAL:\n partialField = new PartialField(schema.name, data, schema, new TemporalParser(schema));\n return new Temporal(partialField, `0-${data.length - 1}`);\n case DimensionSubtype.BINNED:\n partialField = new PartialField(schema.name, data, schema, new BinnedParser());\n return new Binned(partialField, `0-${data.length - 1}`);\n default:\n partialField = new PartialField(schema.name, data, schema, new CategoricalParser());\n return new Categorical(partialField, `0-${data.length - 1}`);\n }\n default:\n partialField = new PartialField(schema.name, data, schema, new CategoricalParser());\n return new Categorical(partialField, `0-${data.length - 1}`);\n }\n}\n\n\n/**\n * Creates a field instance from partialField and rowDiffset.\n *\n * @param {PartialField} partialField - The corresponding partial field.\n * @param {string} rowDiffset - The data subset config.\n * @return {Field} Returns the newly created field instance.\n */\nexport function createUnitFieldFromPartial(partialField, rowDiffset) {\n const { schema } = partialField;\n\n switch (schema.type) {\n case FieldType.MEASURE:\n switch (schema.subtype) {\n case MeasureSubtype.CONTINUOUS:\n return new Continuous(partialField, rowDiffset);\n default:\n return new Continuous(partialField, rowDiffset);\n }\n case FieldType.DIMENSION:\n switch (schema.subtype) {\n case DimensionSubtype.CATEGORICAL:\n return new Categorical(partialField, rowDiffset);\n case DimensionSubtype.TEMPORAL:\n return new Temporal(partialField, rowDiffset);\n case DimensionSubtype.BINNED:\n return new Binned(partialField, rowDiffset);\n default:\n return new Categorical(partialField, rowDiffset);\n }\n default:\n return new Categorical(partialField, rowDiffset);\n }\n}\n\n/**\n * Creates the field instances with input data and schema.\n *\n * @param {Array} dataColumn - The data array for fields.\n * @param {Array} schema - The schema array for fields.\n * @param {Array} headers - The array of header names.\n * @return {Array.} Returns an array of newly created field instances.\n */\nexport function createFields(dataColumn, schema, headers) {\n const headersObj = {};\n\n if (!(headers && headers.length)) {\n headers = schema.map(item => item.name);\n }\n\n headers.forEach((header, i) => {\n headersObj[header] = i;\n });\n\n return schema.map(item => createUnitField(dataColumn[headersObj[item.name]], item));\n}\n","import { DataFormat } from './enums';\n\nexport default {\n dataFormat: DataFormat.AUTO\n};\n","import { columnMajor } from '../utils';\n\n/**\n * Parses and converts data formatted in DSV array to a manageable internal format.\n *\n * @param {Array.} arr - A 2D array containing of the DSV data.\n * @param {Object} options - Option to control the behaviour of the parsing.\n * @param {boolean} [options.firstRowHeader=true] - Whether the first row of the dsv data is header or not.\n * @return {Array} Returns an array of headers and column major data.\n * @example\n *\n * // Sample input data:\n * const data = [\n * [\"a\", \"b\", \"c\"],\n * [1, 2, 3],\n * [4, 5, 6],\n * [7, 8, 9]\n * ];\n */\nfunction DSVArr (arr, schema, options) {\n if (!Array.isArray(schema)) {\n throw new Error('Schema missing or is in an unsupported format');\n }\n const defaultOption = {\n firstRowHeader: true,\n };\n const schemaFields = schema.map(unitSchema => unitSchema.name);\n options = Object.assign({}, defaultOption, options);\n\n const columns = [];\n const push = columnMajor(columns);\n\n if (options.firstRowHeader) {\n // If header present then remove the first header row.\n // Do in-place mutation to save space.\n arr.splice(0, 1)[0];\n }\n\n arr.forEach(field => push(...field));\n\n return [schemaFields, columns];\n}\n\nexport default DSVArr;\n","var EOL = {},\n EOF = {},\n QUOTE = 34,\n NEWLINE = 10,\n RETURN = 13;\n\nfunction objectConverter(columns) {\n return new Function(\"d\", \"return {\" + columns.map(function(name, i) {\n return JSON.stringify(name) + \": d[\" + i + \"]\";\n }).join(\",\") + \"}\");\n}\n\nfunction customConverter(columns, f) {\n var object = objectConverter(columns);\n return function(row, i) {\n return f(object(row), i, columns);\n };\n}\n\n// Compute unique columns in order of discovery.\nfunction inferColumns(rows) {\n var columnSet = Object.create(null),\n columns = [];\n\n rows.forEach(function(row) {\n for (var column in row) {\n if (!(column in columnSet)) {\n columns.push(columnSet[column] = column);\n }\n }\n });\n\n return columns;\n}\n\nfunction pad(value, width) {\n var s = value + \"\", length = s.length;\n return length < width ? new Array(width - length + 1).join(0) + s : s;\n}\n\nfunction formatYear(year) {\n return year < 0 ? \"-\" + pad(-year, 6)\n : year > 9999 ? \"+\" + pad(year, 6)\n : pad(year, 4);\n}\n\nfunction formatDate(date) {\n var hours = date.getUTCHours(),\n minutes = date.getUTCMinutes(),\n seconds = date.getUTCSeconds(),\n milliseconds = date.getUTCMilliseconds();\n return isNaN(date) ? \"Invalid Date\"\n : formatYear(date.getUTCFullYear(), 4) + \"-\" + pad(date.getUTCMonth() + 1, 2) + \"-\" + pad(date.getUTCDate(), 2)\n + (milliseconds ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \":\" + pad(seconds, 2) + \".\" + pad(milliseconds, 3) + \"Z\"\n : seconds ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \":\" + pad(seconds, 2) + \"Z\"\n : minutes || hours ? \"T\" + pad(hours, 2) + \":\" + pad(minutes, 2) + \"Z\"\n : \"\");\n}\n\nexport default function(delimiter) {\n var reFormat = new RegExp(\"[\\\"\" + delimiter + \"\\n\\r]\"),\n DELIMITER = delimiter.charCodeAt(0);\n\n function parse(text, f) {\n var convert, columns, rows = parseRows(text, function(row, i) {\n if (convert) return convert(row, i - 1);\n columns = row, convert = f ? customConverter(row, f) : objectConverter(row);\n });\n rows.columns = columns || [];\n return rows;\n }\n\n function parseRows(text, f) {\n var rows = [], // output rows\n N = text.length,\n I = 0, // current character index\n n = 0, // current line number\n t, // current token\n eof = N <= 0, // current token followed by EOF?\n eol = false; // current token followed by EOL?\n\n // Strip the trailing newline.\n if (text.charCodeAt(N - 1) === NEWLINE) --N;\n if (text.charCodeAt(N - 1) === RETURN) --N;\n\n function token() {\n if (eof) return EOF;\n if (eol) return eol = false, EOL;\n\n // Unescape quotes.\n var i, j = I, c;\n if (text.charCodeAt(j) === QUOTE) {\n while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE);\n if ((i = I) >= N) eof = true;\n else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true;\n else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; }\n return text.slice(j + 1, i - 1).replace(/\"\"/g, \"\\\"\");\n }\n\n // Find next delimiter or newline.\n while (I < N) {\n if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true;\n else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; }\n else if (c !== DELIMITER) continue;\n return text.slice(j, i);\n }\n\n // Return last token before EOF.\n return eof = true, text.slice(j, N);\n }\n\n while ((t = token()) !== EOF) {\n var row = [];\n while (t !== EOL && t !== EOF) row.push(t), t = token();\n if (f && (row = f(row, n++)) == null) continue;\n rows.push(row);\n }\n\n return rows;\n }\n\n function preformatBody(rows, columns) {\n return rows.map(function(row) {\n return columns.map(function(column) {\n return formatValue(row[column]);\n }).join(delimiter);\n });\n }\n\n function format(rows, columns) {\n if (columns == null) columns = inferColumns(rows);\n return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join(\"\\n\");\n }\n\n function formatBody(rows, columns) {\n if (columns == null) columns = inferColumns(rows);\n return preformatBody(rows, columns).join(\"\\n\");\n }\n\n function formatRows(rows) {\n return rows.map(formatRow).join(\"\\n\");\n }\n\n function formatRow(row) {\n return row.map(formatValue).join(delimiter);\n }\n\n function formatValue(value) {\n return value == null ? \"\"\n : value instanceof Date ? formatDate(value)\n : reFormat.test(value += \"\") ? \"\\\"\" + value.replace(/\"/g, \"\\\"\\\"\") + \"\\\"\"\n : value;\n }\n\n return {\n parse: parse,\n parseRows: parseRows,\n format: format,\n formatBody: formatBody,\n formatRows: formatRows\n };\n}\n","import dsv from \"./dsv\";\n\nvar csv = dsv(\",\");\n\nexport var csvParse = csv.parse;\nexport var csvParseRows = csv.parseRows;\nexport var csvFormat = csv.format;\nexport var csvFormatBody = csv.formatBody;\nexport var csvFormatRows = csv.formatRows;\n","import dsv from \"./dsv\";\n\nvar tsv = dsv(\"\\t\");\n\nexport var tsvParse = tsv.parse;\nexport var tsvParseRows = tsv.parseRows;\nexport var tsvFormat = tsv.format;\nexport var tsvFormatBody = tsv.formatBody;\nexport var tsvFormatRows = tsv.formatRows;\n","import { dsvFormat as d3Dsv } from 'd3-dsv';\nimport DSVArr from './dsv-arr';\n\n/**\n * Parses and converts data formatted in DSV string to a manageable internal format.\n *\n * @todo Support to be given for https://tools.ietf.org/html/rfc4180.\n * @todo Sample implementation https://github.com/knrz/CSV.js/.\n *\n * @param {string} str - The input DSV string.\n * @param {Object} options - Option to control the behaviour of the parsing.\n * @param {boolean} [options.firstRowHeader=true] - Whether the first row of the dsv string data is header or not.\n * @param {string} [options.fieldSeparator=\",\"] - The separator of two consecutive field.\n * @return {Array} Returns an array of headers and column major data.\n * @example\n *\n * // Sample input data:\n * const data = `\n * a,b,c\n * 1,2,3\n * 4,5,6\n * 7,8,9\n * `\n */\nfunction DSVStr (str, schema, options) {\n const defaultOption = {\n firstRowHeader: true,\n fieldSeparator: ','\n };\n options = Object.assign({}, defaultOption, options);\n\n const dsv = d3Dsv(options.fieldSeparator);\n return DSVArr(dsv.parseRows(str), schema, options);\n}\n\nexport default DSVStr;\n","import { columnMajor } from '../utils';\n\n/**\n * Parses and converts data formatted in JSON to a manageable internal format.\n *\n * @param {Array.} arr - The input data formatted in JSON.\n * @return {Array.} Returns an array of headers and column major data.\n * @example\n *\n * // Sample input data:\n * const data = [\n * {\n * \"a\": 1,\n * \"b\": 2,\n * \"c\": 3\n * },\n * {\n * \"a\": 4,\n * \"b\": 5,\n * \"c\": 6\n * },\n * {\n * \"a\": 7,\n * \"b\": 8,\n * \"c\": 9\n * }\n * ];\n */\nfunction FlatJSON (arr, schema) {\n if (!Array.isArray(schema)) {\n throw new Error('Schema missing or is in an unsupported format');\n }\n\n const header = {};\n let i = 0;\n let insertionIndex;\n const columns = [];\n const push = columnMajor(columns);\n const schemaFieldsName = schema.map(unitSchema => unitSchema.name);\n\n arr.forEach((item) => {\n const fields = [];\n schemaFieldsName.forEach((unitSchema) => {\n if (unitSchema in header) {\n insertionIndex = header[unitSchema];\n } else {\n header[unitSchema] = i++;\n insertionIndex = i - 1;\n }\n fields[insertionIndex] = item[unitSchema];\n });\n push(...fields);\n });\n\n return [Object.keys(header), columns];\n}\n\nexport default FlatJSON;\n","import FlatJSON from './flat-json';\nimport DSVArr from './dsv-arr';\nimport DSVStr from './dsv-str';\nimport { detectDataFormat } from '../utils';\n\n/**\n * Parses the input data and detect the format automatically.\n *\n * @param {string|Array} data - The input data.\n * @param {Object} options - An optional config specific to data format.\n * @return {Array.} Returns an array of headers and column major data.\n */\nfunction Auto (data, schema, options) {\n const converters = { FlatJSON, DSVStr, DSVArr };\n const dataFormat = detectDataFormat(data);\n\n if (!dataFormat) {\n throw new Error('Couldn\\'t detect the data format');\n }\n\n return converters[dataFormat](data, schema, options);\n}\n\nexport default Auto;\n","import { FieldType, FilteringMode, DimensionSubtype, MeasureSubtype, DataFormat } from './enums';\nimport fieldStore from './field-store';\nimport Value from './value';\nimport {\n rowDiffsetIterator\n} from './operator';\nimport { DM_DERIVATIVES, LOGICAL_OPERATORS } from './constants';\nimport { createFields, createUnitFieldFromPartial } from './field-creator';\nimport defaultConfig from './default-config';\nimport * as converter from './converter';\nimport { extend2, detectDataFormat } from './utils';\n\n/**\n * Prepares the selection data.\n */\nfunction prepareSelectionData (fields, formattedData, rawData, i) {\n const resp = {};\n\n for (const [key, field] of fields.entries()) {\n resp[field.name()] = new Value(formattedData[key][i], rawData[key][i], field);\n }\n return resp;\n}\n\nexport function prepareJoinData (fields) {\n const resp = {};\n\n for (const key in fields) {\n resp[key] = new Value(fields[key].formattedValue, fields[key].rawValue, key);\n }\n return resp;\n}\n\nexport const updateFields = ([rowDiffset, colIdentifier], partialFieldspace, fieldStoreName) => {\n let collID = colIdentifier.length ? colIdentifier.split(',') : [];\n let partialFieldMap = partialFieldspace.fieldsObj();\n let newFields = collID.map(coll => createUnitFieldFromPartial(partialFieldMap[coll].partialField, rowDiffset));\n return fieldStore.createNamespace(newFields, fieldStoreName);\n};\n\nexport const persistCurrentDerivation = (model, operation, config = {}, criteriaFn) => {\n if (operation === DM_DERIVATIVES.COMPOSE) {\n model._derivation.length = 0;\n model._derivation.push(...criteriaFn);\n } else {\n model._derivation.push({\n op: operation,\n meta: config,\n criteria: criteriaFn\n });\n }\n};\nexport const persistAncestorDerivation = (sourceDm, newDm) => {\n newDm._ancestorDerivation.push(...sourceDm._ancestorDerivation, ...sourceDm._derivation);\n};\n\nexport const persistDerivations = (sourceDm, model, operation, config = {}, criteriaFn) => {\n persistCurrentDerivation(model, operation, config, criteriaFn);\n persistAncestorDerivation(sourceDm, model);\n};\n\nconst selectModeMap = {\n [FilteringMode.NORMAL]: {\n diffIndex: ['rowDiffset'],\n calcDiff: [true, false]\n },\n [FilteringMode.INVERSE]: {\n diffIndex: ['rejectRowDiffset'],\n calcDiff: [false, true]\n },\n [FilteringMode.ALL]: {\n diffIndex: ['rowDiffset', 'rejectRowDiffset'],\n calcDiff: [true, true]\n }\n};\n\nconst generateRowDiffset = (rowDiffset, i, lastInsertedValue) => {\n if (lastInsertedValue !== -1 && i === (lastInsertedValue + 1)) {\n const li = rowDiffset.length - 1;\n\n rowDiffset[li] = `${rowDiffset[li].split('-')[0]}-${i}`;\n } else {\n rowDiffset.push(`${i}`);\n }\n};\n\nexport const selectRowDiffsetIterator = (rowDiffset, checker, mode) => {\n let lastInsertedValueSel = -1;\n let lastInsertedValueRej = -1;\n const newRowDiffSet = [];\n const rejRowDiffSet = [];\n\n const [shouldSelect, shouldReject] = selectModeMap[mode].calcDiff;\n\n rowDiffsetIterator(rowDiffset, (i) => {\n const checkerResult = checker(i);\n checkerResult && shouldSelect && generateRowDiffset(newRowDiffSet, i, lastInsertedValueSel);\n !checkerResult && shouldReject && generateRowDiffset(rejRowDiffSet, i, lastInsertedValueRej);\n });\n return {\n rowDiffset: newRowDiffSet.join(','),\n rejectRowDiffset: rejRowDiffSet.join(',')\n };\n};\n\n\nexport const rowSplitDiffsetIterator = (rowDiffset, checker, mode, dimensionArr, fieldStoreObj) => {\n let lastInsertedValue = {};\n const splitRowDiffset = {};\n const dimensionMap = {};\n\n rowDiffsetIterator(rowDiffset, (i) => {\n if (checker(i)) {\n let hash = '';\n\n let dimensionSet = { keys: {} };\n\n dimensionArr.forEach((_) => {\n const data = fieldStoreObj[_].partialField.data[i];\n hash = `${hash}-${data}`;\n dimensionSet.keys[_] = data;\n });\n\n if (splitRowDiffset[hash] === undefined) {\n splitRowDiffset[hash] = [];\n lastInsertedValue[hash] = -1;\n dimensionMap[hash] = dimensionSet;\n }\n\n generateRowDiffset(splitRowDiffset[hash], i, lastInsertedValue[hash]);\n lastInsertedValue[hash] = i;\n }\n });\n\n return {\n splitRowDiffset,\n dimensionMap\n };\n};\n\n\nexport const selectHelper = (clonedDm, selectFn, config, sourceDm, iterator) => {\n let cachedStore = {};\n let cloneProvider = () => sourceDm.detachedRoot();\n const { mode } = config;\n const rowDiffset = clonedDm._rowDiffset;\n const fields = clonedDm.getPartialFieldspace().fields;\n const formattedFieldsData = fields.map(field => field.formattedData());\n const rawFieldsData = fields.map(field => field.data());\n\n const selectorHelperFn = index => selectFn(\n prepareSelectionData(fields, formattedFieldsData, rawFieldsData, index),\n index,\n cloneProvider,\n cachedStore\n );\n\n return iterator(rowDiffset, selectorHelperFn, mode);\n};\n\nexport const cloneWithAllFields = (model) => {\n const clonedDm = model.clone(false);\n const partialFieldspace = model.getPartialFieldspace();\n clonedDm._colIdentifier = partialFieldspace.fields.map(f => f.name()).join(',');\n\n // flush out cached namespace values on addition of new fields\n partialFieldspace._cachedFieldsObj = null;\n partialFieldspace._cachedDimension = null;\n partialFieldspace._cachedMeasure = null;\n clonedDm.__calculateFieldspace().calculateFieldsConfig();\n\n return clonedDm;\n};\n\nconst getKey = (arr, data, fn) => {\n let key = fn(arr, data, 0);\n\n for (let i = 1, len = arr.length; i < len; i++) {\n key = `${key},${fn(arr, data, i)}`;\n }\n return key;\n};\n\nexport const filterPropagationModel = (model, propModels, config = {}) => {\n let fns = [];\n const operation = config.operation || LOGICAL_OPERATORS.AND;\n const filterByMeasure = config.filterByMeasure || false;\n const clonedModel = cloneWithAllFields(model);\n const modelFieldsConfig = clonedModel.getFieldsConfig();\n\n if (!propModels.length) {\n fns = [() => false];\n } else {\n fns = propModels.map(propModel => ((dataModel) => {\n let keyFn;\n const dataObj = dataModel.getData();\n const fieldsConfig = dataModel.getFieldsConfig();\n const dimensions = Object.keys(dataModel.getFieldspace().getDimension())\n .filter(d => d in modelFieldsConfig);\n const dLen = dimensions.length;\n const indices = dimensions.map(d =>\n fieldsConfig[d].index);\n const measures = Object.keys(dataModel.getFieldspace().getMeasure())\n .filter(d => d in modelFieldsConfig);\n const fieldsSpace = dataModel.getFieldspace().fieldsObj();\n const data = dataObj.data;\n const domain = measures.reduce((acc, v) => {\n acc[v] = fieldsSpace[v].domain();\n return acc;\n }, {});\n const valuesMap = {};\n\n keyFn = (arr, row, idx) => row[arr[idx]];\n if (dLen) {\n data.forEach((row) => {\n const key = getKey(indices, row, keyFn);\n valuesMap[key] = 1;\n });\n }\n\n keyFn = (arr, fields, idx) => fields[arr[idx]].internalValue;\n return data.length ? (fields) => {\n const present = dLen ? valuesMap[getKey(dimensions, fields, keyFn)] : true;\n\n if (filterByMeasure) {\n return measures.every(field => fields[field].internalValue >= domain[field][0] &&\n fields[field].internalValue <= domain[field][1]) && present;\n }\n return present;\n } : () => false;\n })(propModel));\n }\n\n let filteredModel;\n if (operation === LOGICAL_OPERATORS.AND) {\n filteredModel = clonedModel.select(fields => fns.every(fn => fn(fields)), {\n saveChild: false\n });\n } else {\n filteredModel = clonedModel.select(fields => fns.some(fn => fn(fields)), {\n saveChild: false\n });\n }\n\n return filteredModel;\n};\n\n\nexport const splitWithSelect = (sourceDm, dimensionArr, reducerFn = val => val, config) => {\n const {\n saveChild,\n } = config;\n const fieldStoreObj = sourceDm.getFieldspace().fieldsObj();\n\n const {\n splitRowDiffset,\n dimensionMap\n } = selectHelper(\n sourceDm.clone(saveChild),\n reducerFn,\n config,\n sourceDm,\n (...params) => rowSplitDiffsetIterator(...params, dimensionArr, fieldStoreObj)\n );\n\n const clonedDMs = [];\n Object.keys(splitRowDiffset).sort().forEach((e) => {\n if (splitRowDiffset[e]) {\n const cloned = sourceDm.clone(saveChild);\n const derivation = dimensionMap[e];\n cloned._rowDiffset = splitRowDiffset[e].join(',');\n cloned.__calculateFieldspace().calculateFieldsConfig();\n\n const derivationFormula = fields => dimensionArr.every(_ => fields[_].internalValue === derivation.keys[_]);\n // Store reference to child model and selector function\n if (saveChild) {\n persistDerivations(sourceDm, cloned, DM_DERIVATIVES.SELECT, config, derivationFormula);\n }\n cloned._derivation[cloned._derivation.length - 1].meta = dimensionMap[e];\n\n clonedDMs.push(cloned);\n }\n });\n\n\n return clonedDMs;\n};\nexport const addDiffsetToClonedDm = (clonedDm, rowDiffset, sourceDm, selectConfig, selectFn) => {\n clonedDm._rowDiffset = rowDiffset;\n clonedDm.__calculateFieldspace().calculateFieldsConfig();\n persistDerivations(\n sourceDm,\n clonedDm,\n DM_DERIVATIVES.SELECT,\n { config: selectConfig },\n selectFn\n );\n};\n\n\nexport const cloneWithSelect = (sourceDm, selectFn, selectConfig, cloneConfig) => {\n let extraCloneDm = {};\n\n let { mode } = selectConfig;\n\n const cloned = sourceDm.clone(cloneConfig.saveChild);\n const setOfRowDiffsets = selectHelper(\n cloned,\n selectFn,\n selectConfig,\n sourceDm,\n selectRowDiffsetIterator\n );\n const diffIndex = selectModeMap[mode].diffIndex;\n\n addDiffsetToClonedDm(cloned, setOfRowDiffsets[diffIndex[0]], sourceDm, selectConfig, selectFn);\n\n if (diffIndex.length > 1) {\n extraCloneDm = sourceDm.clone(cloneConfig.saveChild);\n addDiffsetToClonedDm(extraCloneDm, setOfRowDiffsets[diffIndex[1]], sourceDm, selectConfig, selectFn);\n return [cloned, extraCloneDm];\n }\n\n return cloned;\n};\n\nexport const cloneWithProject = (sourceDm, projField, config, allFields) => {\n const cloned = sourceDm.clone(config.saveChild);\n let projectionSet = projField;\n if (config.mode === FilteringMode.INVERSE) {\n projectionSet = allFields.filter(fieldName => projField.indexOf(fieldName) === -1);\n }\n // cloned._colIdentifier = sourceDm._colIdentifier.split(',')\n // .filter(coll => projectionSet.indexOf(coll) !== -1).join();\n cloned._colIdentifier = projectionSet.join(',');\n cloned.__calculateFieldspace().calculateFieldsConfig();\n\n persistDerivations(\n sourceDm,\n cloned,\n DM_DERIVATIVES.PROJECT,\n { projField, config, actualProjField: projectionSet },\n null\n );\n\n return cloned;\n};\n\n\nexport const splitWithProject = (sourceDm, projFieldSet, config, allFields) =>\n projFieldSet.map(projFields =>\n cloneWithProject(sourceDm, projFields, config, allFields));\n\nexport const sanitizeUnitSchema = (unitSchema) => {\n // Do deep clone of the unit schema as the user might change it later.\n unitSchema = extend2({}, unitSchema);\n if (!unitSchema.type) {\n unitSchema.type = FieldType.DIMENSION;\n }\n\n if (!unitSchema.subtype) {\n switch (unitSchema.type) {\n case FieldType.MEASURE:\n unitSchema.subtype = MeasureSubtype.CONTINUOUS;\n break;\n default:\n case FieldType.DIMENSION:\n unitSchema.subtype = DimensionSubtype.CATEGORICAL;\n break;\n }\n }\n\n return unitSchema;\n};\n\nexport const validateUnitSchema = (unitSchema) => {\n const supportedMeasureSubTypes = [MeasureSubtype.CONTINUOUS];\n const supportedDimSubTypes = [\n DimensionSubtype.CATEGORICAL,\n DimensionSubtype.BINNED,\n DimensionSubtype.TEMPORAL,\n DimensionSubtype.GEO\n ];\n const { type, subtype, name } = unitSchema;\n\n switch (type) {\n case FieldType.DIMENSION:\n if (supportedDimSubTypes.indexOf(subtype) === -1) {\n throw new Error(`DataModel doesn't support dimension field subtype ${subtype} used for ${name} field`);\n }\n break;\n case FieldType.MEASURE:\n if (supportedMeasureSubTypes.indexOf(subtype) === -1) {\n throw new Error(`DataModel doesn't support measure field subtype ${subtype} used for ${name} field`);\n }\n break;\n default:\n throw new Error(`DataModel doesn't support field type ${type} used for ${name} field`);\n }\n};\n\nexport const sanitizeAndValidateSchema = schema => schema.map((unitSchema) => {\n unitSchema = sanitizeUnitSchema(unitSchema);\n validateUnitSchema(unitSchema);\n return unitSchema;\n});\n\nexport const resolveFieldName = (schema, dataHeader) => {\n schema.forEach((unitSchema) => {\n const fieldNameAs = unitSchema.as;\n if (!fieldNameAs) { return; }\n\n const idx = dataHeader.indexOf(unitSchema.name);\n dataHeader[idx] = fieldNameAs;\n unitSchema.name = fieldNameAs;\n delete unitSchema.as;\n });\n};\n\nexport const updateData = (relation, data, schema, options) => {\n schema = sanitizeAndValidateSchema(schema);\n options = Object.assign(Object.assign({}, defaultConfig), options);\n const converterFn = converter[options.dataFormat];\n\n if (!(converterFn && typeof converterFn === 'function')) {\n throw new Error(`No converter function found for ${options.dataFormat} format`);\n }\n\n const [header, formattedData] = converterFn(data, schema, options);\n resolveFieldName(schema, header);\n const fieldArr = createFields(formattedData, schema, header);\n\n // This will create a new fieldStore with the fields\n const nameSpace = fieldStore.createNamespace(fieldArr, options.name);\n relation._partialFieldspace = nameSpace;\n\n // If data is provided create the default colIdentifier and rowDiffset\n relation._rowDiffset = formattedData.length && formattedData[0].length ? `0-${formattedData[0].length - 1}` : '';\n\n // This stores the value objects which is passed to the filter method when selection operation is done.\n const valueObjects = [];\n const { fields } = nameSpace;\n const rawFieldsData = fields.map(field => field.data());\n const formattedFieldsData = fields.map(field => field.formattedData());\n rowDiffsetIterator(relation._rowDiffset, (i) => {\n valueObjects[i] = prepareSelectionData(fields, formattedFieldsData, rawFieldsData, i);\n });\n nameSpace._cachedValueObjects = valueObjects;\n\n relation._colIdentifier = (schema.map(_ => _.name)).join();\n relation._dataFormat = options.dataFormat === DataFormat.AUTO ? detectDataFormat(data) : options.dataFormat;\n return relation;\n};\n\nexport const fieldInSchema = (schema, field) => {\n let i = 0;\n\n for (; i < schema.length; ++i) {\n if (field === schema[i].name) {\n return {\n name: field,\n type: schema[i].subtype || schema[i].type,\n index: i,\n };\n }\n }\n return null;\n};\n\nexport const getDerivationArguments = (derivation) => {\n let params = [];\n let operation;\n operation = derivation.op;\n switch (operation) {\n case DM_DERIVATIVES.SELECT:\n params = [derivation.criteria];\n break;\n case DM_DERIVATIVES.PROJECT:\n params = [derivation.meta.actualProjField];\n break;\n case DM_DERIVATIVES.SORT:\n params = [derivation.criteria];\n break;\n case DM_DERIVATIVES.GROUPBY:\n operation = 'groupBy';\n params = [derivation.meta.groupByString.split(','), derivation.criteria];\n break;\n default:\n operation = null;\n }\n\n return {\n operation,\n params\n };\n};\n\nconst applyExistingOperationOnModel = (propModel, dataModel) => {\n const derivations = dataModel.getDerivations();\n let selectionModel = propModel;\n\n derivations.forEach((derivation) => {\n if (!derivation) {\n return;\n }\n\n const { operation, params } = getDerivationArguments(derivation);\n if (operation) {\n selectionModel = selectionModel[operation](...params, {\n saveChild: false\n });\n }\n });\n\n return selectionModel;\n};\n\nconst getFilteredModel = (propModel, path) => {\n for (let i = 0, len = path.length; i < len; i++) {\n const model = path[i];\n propModel = applyExistingOperationOnModel(propModel, model);\n }\n return propModel;\n};\n\nconst propagateIdentifiers = (dataModel, propModel, config = {}, propModelInf = {}) => {\n const nonTraversingModel = propModelInf.nonTraversingModel;\n const excludeModels = propModelInf.excludeModels || [];\n\n if (dataModel === nonTraversingModel) {\n return;\n }\n\n const propagate = excludeModels.length ? excludeModels.indexOf(dataModel) === -1 : true;\n\n propagate && dataModel.handlePropagation(propModel, config);\n\n const children = dataModel._children;\n children.forEach((child) => {\n const selectionModel = applyExistingOperationOnModel(propModel, child);\n propagateIdentifiers(child, selectionModel, config, propModelInf);\n });\n};\n\nexport const getRootGroupByModel = (model) => {\n while (model._parent && model._derivation.find(d => d.op !== DM_DERIVATIVES.GROUPBY)) {\n model = model._parent;\n }\n return model;\n};\n\nexport const getRootDataModel = (model) => {\n while (model._parent) {\n model = model._parent;\n }\n return model;\n};\n\nexport const getPathToRootModel = (model, path = []) => {\n while (model._parent) {\n path.push(model);\n model = model._parent;\n }\n return path;\n};\n\nexport const propagateToAllDataModels = (identifiers, rootModels, propagationInf, config) => {\n let criteria;\n let propModel;\n const { propagationNameSpace, propagateToSource } = propagationInf;\n const propagationSourceId = propagationInf.sourceId;\n const propagateInterpolatedValues = config.propagateInterpolatedValues;\n const filterFn = (entry) => {\n const filter = config.filterFn || (() => true);\n return filter(entry, config);\n };\n\n let criterias = [];\n\n if (identifiers === null && config.persistent !== true) {\n criterias = [{\n criteria: []\n }];\n criteria = [];\n } else {\n let actionCriterias = Object.values(propagationNameSpace.mutableActions);\n if (propagateToSource !== false) {\n actionCriterias = actionCriterias.filter(d => d.config.sourceId !== propagationSourceId);\n }\n\n const filteredCriteria = actionCriterias.filter(filterFn).map(action => action.config.criteria);\n\n const excludeModels = [];\n\n if (propagateToSource !== false) {\n const sourceActionCriterias = Object.values(propagationNameSpace.mutableActions);\n\n sourceActionCriterias.forEach((actionInf) => {\n const actionConf = actionInf.config;\n if (actionConf.applyOnSource === false && actionConf.action === config.action &&\n actionConf.sourceId !== propagationSourceId) {\n excludeModels.push(actionInf.model);\n criteria = sourceActionCriterias.filter(d => d !== actionInf).map(d => d.config.criteria);\n criteria.length && criterias.push({\n criteria,\n models: actionInf.model,\n path: getPathToRootModel(actionInf.model)\n });\n }\n });\n }\n\n\n criteria = [].concat(...[...filteredCriteria, identifiers]).filter(d => d !== null);\n criterias.push({\n criteria,\n excludeModels: [...excludeModels, ...config.excludeModels || []]\n });\n }\n\n const rootModel = rootModels.model;\n\n const propConfig = Object.assign({\n sourceIdentifiers: identifiers,\n propagationSourceId\n }, config);\n\n const rootGroupByModel = rootModels.groupByModel;\n if (propagateInterpolatedValues && rootGroupByModel) {\n propModel = filterPropagationModel(rootGroupByModel, criteria, {\n filterByMeasure: propagateInterpolatedValues\n });\n propagateIdentifiers(rootGroupByModel, propModel, propConfig);\n }\n\n criterias.forEach((inf) => {\n const propagationModel = filterPropagationModel(rootModel, inf.criteria);\n const path = inf.path;\n\n if (path) {\n const filteredModel = getFilteredModel(propagationModel, path.reverse());\n inf.models.handlePropagation(filteredModel, propConfig);\n } else {\n propagateIdentifiers(rootModel, propagationModel, propConfig, {\n excludeModels: inf.excludeModels,\n nonTraversingModel: propagateInterpolatedValues && rootGroupByModel\n });\n }\n });\n};\n\nexport const propagateImmutableActions = (propagationNameSpace, rootModels, propagationInf) => {\n const immutableActions = propagationNameSpace.immutableActions;\n\n for (const action in immutableActions) {\n const actionInf = immutableActions[action];\n const actionConf = actionInf.config;\n const propagationSourceId = propagationInf.config.sourceId;\n const filterImmutableAction = propagationInf.propConfig.filterImmutableAction ?\n propagationInf.propConfig.filterImmutableAction(actionConf, propagationInf.config) : true;\n if (actionConf.sourceId !== propagationSourceId && filterImmutableAction) {\n const criteriaModel = actionConf.criteria;\n propagateToAllDataModels(criteriaModel, rootModels, {\n propagationNameSpace,\n propagateToSource: false,\n sourceId: propagationSourceId\n }, actionConf);\n }\n }\n};\n\nexport const addToPropNamespace = (propagationNameSpace, config = {}, model) => {\n let sourceNamespace;\n const isMutableAction = config.isMutableAction;\n const criteria = config.criteria;\n const key = `${config.action}-${config.sourceId}`;\n\n if (isMutableAction) {\n sourceNamespace = propagationNameSpace.mutableActions;\n } else {\n sourceNamespace = propagationNameSpace.immutableActions;\n }\n\n if (criteria === null) {\n delete sourceNamespace[key];\n } else {\n sourceNamespace[key] = {\n model,\n config\n };\n }\n\n return this;\n};\n\n\nexport const getNormalizedProFields = (projField, allFields, fieldConfig) => {\n const normalizedProjField = projField.reduce((acc, field) => {\n if (field.constructor.name === 'RegExp') {\n acc.push(...allFields.filter(fieldName => fieldName.search(field) !== -1));\n } else if (field in fieldConfig) {\n acc.push(field);\n }\n return acc;\n }, []);\n return Array.from(new Set(normalizedProjField)).map(field => field.trim());\n};\n\n/**\n * Get the numberFormatted value if numberFormat present,\n * else returns the supplied value.\n * @param {Object} field Field Instance\n * @param {Number|String} value\n * @return {Number|String}\n */\nexport const getNumberFormattedVal = (field, value) => {\n if (field.numberFormat) {\n return field.numberFormat()(value);\n }\n return value;\n};\n","import { FilteringMode } from './enums';\nimport { getUniqueId } from './utils';\nimport {\n updateFields,\n cloneWithSelect,\n cloneWithProject,\n updateData,\n getNormalizedProFields\n} from './helper';\nimport { crossProduct, difference, naturalJoinFilter, union } from './operator';\n\n/**\n * Relation provides the definitions of basic operators of relational algebra like *selection*, *projection*, *union*,\n * *difference* etc.\n *\n * It is extended by {@link DataModel} to inherit the functionalities of relational algebra concept.\n *\n * @class\n * @public\n * @module Relation\n * @namespace DataModel\n */\nclass Relation {\n\n /**\n * Creates a new Relation instance by providing underlying data and schema.\n *\n * @private\n *\n * @param {Object | string | Relation} data - The input tabular data in dsv or json format or\n * an existing Relation instance object.\n * @param {Array} schema - An array of data schema.\n * @param {Object} [options] - The optional options.\n */\n constructor (...params) {\n let source;\n\n this._parent = null;\n this._derivation = [];\n this._ancestorDerivation = [];\n this._children = [];\n\n if (params.length === 1 && ((source = params[0]) instanceof Relation)) {\n // parent datamodel was passed as part of source\n this._colIdentifier = source._colIdentifier;\n this._rowDiffset = source._rowDiffset;\n this._dataFormat = source._dataFormat;\n this._parent = source;\n this._partialFieldspace = this._parent._partialFieldspace;\n this._fieldStoreName = getUniqueId();\n this.__calculateFieldspace().calculateFieldsConfig();\n } else {\n updateData(this, ...params);\n this._fieldStoreName = this._partialFieldspace.name;\n this.__calculateFieldspace().calculateFieldsConfig();\n this._propagationNameSpace = {\n mutableActions: {},\n immutableActions: {}\n };\n }\n }\n\n /**\n * Retrieves the {@link Schema | schema} details for every {@link Field | field} as an array.\n *\n * @public\n *\n * @return {Array.} Array of fields schema.\n * ```\n * [\n * { name: 'Name', type: 'dimension' },\n * { name: 'Miles_per_Gallon', type: 'measure', numberFormat: (val) => `${val} miles / gallon` },\n * { name: 'Cylinder', type: 'dimension' },\n * { name: 'Displacement', type: 'measure', defAggFn: 'max' },\n * { name: 'HorsePower', type: 'measure', defAggFn: 'max' },\n * { name: 'Weight_in_lbs', type: 'measure', defAggFn: 'avg', },\n * { name: 'Acceleration', type: 'measure', defAggFn: 'avg' },\n * { name: 'Year', type: 'dimension', subtype: 'datetime', format: '%Y' },\n * { name: 'Origin' }\n * ]\n * ```\n */\n getSchema () {\n return this.getFieldspace().fields.map(d => d.schema());\n }\n\n /**\n * Returns the name of the {@link DataModel} instance. If no name was specified during {@link DataModel}\n * initialization, then it returns a auto-generated name.\n *\n * @public\n *\n * @return {string} Name of the DataModel instance.\n */\n getName() {\n return this._fieldStoreName;\n }\n\n getFieldspace () {\n return this._fieldspace;\n }\n\n __calculateFieldspace () {\n this._fieldspace = updateFields([this._rowDiffset, this._colIdentifier],\n this.getPartialFieldspace(), this._fieldStoreName);\n return this;\n }\n\n getPartialFieldspace () {\n return this._partialFieldspace;\n }\n\n /**\n * Performs {@link link_of_cross_product | cross-product} between two {@link DataModel} instances and returns a\n * new {@link DataModel} instance containing the results. This operation is also called theta join.\n *\n * Cross product takes two set and create one set where each value of one set is paired with each value of another\n * set.\n *\n * This method takes an optional predicate which filters the generated result rows. If the predicate returns true\n * the combined row is included in the resulatant table.\n *\n * @example\n * let originDM = dm.project(['Origin','Origin_Formal_Name']);\n * let carsDM = dm.project(['Name','Miles_per_Gallon','Origin'])\n *\n * console.log(carsDM.join(originDM)));\n *\n * console.log(carsDM.join(originDM,\n * obj => obj.[originDM.getName()].Origin === obj.[carsDM.getName()].Origin));\n *\n * @text\n * This is chained version of `join` operator. `join` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {DataModel} joinWith - The DataModel to be joined with the current instance DataModel.\n * @param {SelectionPredicate} filterFn - The predicate function that will filter the result of the crossProduct.\n *\n * @return {DataModel} New DataModel instance created after joining.\n */\n join (joinWith, filterFn) {\n return crossProduct(this, joinWith, filterFn);\n }\n\n /**\n * {@link natural_join | Natural join} is a special kind of cross-product join where filtering of rows are performed\n * internally by resolving common fields are from both table and the rows with common value are included.\n *\n * @example\n * let originDM = dm.project(['Origin','Origin_Formal_Name']);\n * let carsDM = dm.project(['Name','Miles_per_Gallon','Origin'])\n *\n * console.log(carsDM.naturalJoin(originDM));\n *\n * @text\n * This is chained version of `naturalJoin` operator. `naturalJoin` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {DataModel} joinWith - The DataModel with which the current instance of DataModel on which the method is\n * called will be joined.\n * @return {DataModel} New DataModel instance created after joining.\n */\n naturalJoin (joinWith) {\n return crossProduct(this, joinWith, naturalJoinFilter(this, joinWith), true);\n }\n\n /**\n * {@link link_to_union | Union} operation can be termed as vertical stacking of all rows from both the DataModel\n * instances, provided that both of the {@link DataModel} instances should have same column names.\n *\n * @example\n * console.log(EuropeanMakerDM.union(USAMakerDM));\n *\n * @text\n * This is chained version of `naturalJoin` operator. `naturalJoin` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {DataModel} unionWith - DataModel instance for which union has to be applied with the instance on which\n * the method is called\n *\n * @return {DataModel} New DataModel instance with the result of the operation\n */\n union (unionWith) {\n return union(this, unionWith);\n }\n\n /**\n * {@link link_to_difference | Difference } operation only include rows which are present in the datamodel on which\n * it was called but not on the one passed as argument.\n *\n * @example\n * console.log(highPowerDM.difference(highExpensiveDM));\n *\n * @text\n * This is chained version of `naturalJoin` operator. `naturalJoin` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {DataModel} differenceWith - DataModel instance for which difference has to be applied with the instance\n * on which the method is called\n * @return {DataModel} New DataModel instance with the result of the operation\n */\n difference (differenceWith) {\n return difference(this, differenceWith);\n }\n\n /**\n * {@link link_to_selection | Selection} is a row filtering operation. It expects a predicate and an optional mode\n * which control which all rows should be included in the resultant DataModel instance.\n *\n * {@link SelectionPredicate} is a function which returns a boolean value. For selection operation the selection\n * function is called for each row of DataModel instance with the current row passed as argument.\n *\n * After executing {@link SelectionPredicate} the rows are labeled as either an entry of selection set or an entry\n * of rejection set.\n *\n * {@link FilteringMode} operates on the selection and rejection set to determine which one would reflect in the\n * resultant datamodel.\n *\n * @warning\n * Selection and rejection set is only a logical idea for concept explanation purpose.\n *\n * @example\n * // with selection mode NORMAL:\n * const normDt = dt.select(fields => fields.Origin.value === \"USA\")\n * console.log(normDt));\n *\n * // with selection mode INVERSE:\n * const inverDt = dt.select(fields => fields.Origin.value === \"USA\", { mode: DataModel.FilteringMode.INVERSE })\n * console.log(inverDt);\n *\n * // with selection mode ALL:\n * const dtArr = dt.select(fields => fields.Origin.value === \"USA\", { mode: DataModel.FilteringMode.ALL })\n * // print the selected parts\n * console.log(dtArr[0]);\n * // print the inverted parts\n * console.log(dtArr[1]);\n *\n * @text\n * This is chained version of `select` operator. `select` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {Function} selectFn - The predicate function which is called for each row with the current row.\n * ```\n * function (row, i, cloneProvider, store) { ... }\n * ```\n * @param {Object} config - The configuration object to control the inclusion exclusion of a row in resultant\n * DataModel instance.\n * @param {FilteringMode} [config.mode=FilteringMode.NORMAL] - The mode of the selection.\n * @return {DataModel} Returns the new DataModel instance(s) after operation.\n */\n select (selectFn, config) {\n const defConfig = {\n mode: FilteringMode.NORMAL,\n saveChild: true\n };\n config = Object.assign({}, defConfig, config);\n config.mode = config.mode || defConfig.mode;\n\n const cloneConfig = { saveChild: config.saveChild };\n return cloneWithSelect(\n this,\n selectFn,\n config,\n cloneConfig\n );\n }\n\n /**\n * Retrieves a boolean value if the current {@link DataModel} instance has data.\n *\n * @example\n * const schema = [\n * { name: 'CarName', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n * const data = [];\n *\n * const dt = new DataModel(data, schema);\n * console.log(dt.isEmpty());\n *\n * @public\n *\n * @return {Boolean} True if the datamodel has no data, otherwise false.\n */\n isEmpty () {\n return !this._rowDiffset.length || !this._colIdentifier.length;\n }\n\n /**\n * Creates a clone from the current DataModel instance with child parent relationship.\n *\n * @private\n * @param {boolean} [saveChild=true] - Whether the cloned instance would be recorded in the parent instance.\n * @return {DataModel} - Returns the newly cloned DataModel instance.\n */\n clone (saveChild = true) {\n const clonedDm = new this.constructor(this);\n if (saveChild) {\n clonedDm.setParent(this);\n } else {\n clonedDm.setParent(null);\n }\n return clonedDm;\n }\n\n /**\n * {@link Projection} is filter column (field) operation. It expects list of fields' name and either include those\n * or exclude those based on {@link FilteringMode} on the resultant variable.\n *\n * Projection expects array of fields name based on which it creates the selection and rejection set. All the field\n * whose name is present in array goes in selection set and rest of the fields goes in rejection set.\n *\n * {@link FilteringMode} operates on the selection and rejection set to determine which one would reflect in the\n * resulatant datamodel.\n *\n * @warning\n * Selection and rejection set is only a logical idea for concept explanation purpose.\n *\n * @example\n * const dm = new DataModel(data, schema);\n *\n * // with projection mode NORMAL:\n * const normDt = dt.project([\"Name\", \"HorsePower\"]);\n * console.log(normDt.getData());\n *\n * // with projection mode INVERSE:\n * const inverDt = dt.project([\"Name\", \"HorsePower\"], { mode: DataModel.FilteringMode.INVERSE })\n * console.log(inverDt.getData());\n *\n * // with selection mode ALL:\n * const dtArr = dt.project([\"Name\", \"HorsePower\"], { mode: DataModel.FilteringMode.ALL })\n * // print the normal parts\n * console.log(dtArr[0].getData());\n * // print the inverted parts\n * console.log(dtArr[1].getData());\n *\n * @text\n * This is chained version of `select` operator. `select` can also be used as\n * {@link link_to_join_op | functional operator}.\n *\n * @public\n *\n * @param {Array.} projField - An array of column names in string or regular expression.\n * @param {Object} [config] - An optional config to control the creation of new DataModel\n * @param {FilteringMode} [config.mode=FilteringMode.NORMAL] - Mode of the projection\n *\n * @return {DataModel} Returns the new DataModel instance after operation.\n */\n project (projField, config) {\n const defConfig = {\n mode: FilteringMode.NORMAL,\n saveChild: true\n };\n config = Object.assign({}, defConfig, config);\n const fieldConfig = this.getFieldsConfig();\n const allFields = Object.keys(fieldConfig);\n const { mode } = config;\n const normalizedProjField = getNormalizedProFields(projField, allFields, fieldConfig);\n\n let dataModel;\n\n if (mode === FilteringMode.ALL) {\n let projectionClone = cloneWithProject(this, normalizedProjField, {\n mode: FilteringMode.NORMAL,\n saveChild: config.saveChild\n }, allFields);\n let rejectionClone = cloneWithProject(this, normalizedProjField, {\n mode: FilteringMode.INVERSE,\n saveChild: config.saveChild\n }, allFields);\n dataModel = [projectionClone, rejectionClone];\n } else {\n let projectionClone = cloneWithProject(this, normalizedProjField, config, allFields);\n dataModel = projectionClone;\n }\n\n return dataModel;\n }\n\n getFieldsConfig () {\n return this._fieldConfig;\n }\n\n calculateFieldsConfig () {\n this._fieldConfig = this._fieldspace.fields.reduce((acc, fieldObj, i) => {\n acc[fieldObj.name()] = {\n index: i,\n def: fieldObj.schema(),\n };\n return acc;\n }, {});\n return this;\n }\n\n\n /**\n * Frees up the resources associated with the current DataModel instance and breaks all the links instance has in\n * the DAG.\n *\n * @public\n */\n dispose () {\n this._parent && this._parent.removeChild(this);\n this._parent = null;\n this._children.forEach((child) => {\n child._parent = null;\n });\n this._children = [];\n }\n\n /**\n * Removes the specified child {@link DataModel} from the child list of the current {@link DataModel} instance.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n *\n * const dt2 = dt.select(fields => fields.Origin.value === \"USA\")\n * dt.removeChild(dt2);\n *\n * @private\n *\n * @param {DataModel} child - Delegates the parent to remove this child.\n */\n removeChild (child) {\n let idx = this._children.findIndex(sibling => sibling === child);\n idx !== -1 ? this._children.splice(idx, 1) : true;\n }\n\n /**\n * Sets the specified {@link DataModel} as a parent for the current {@link DataModel} instance.\n *\n * @param {DataModel} parent - The datamodel instance which will act as parent.\n */\n setParent (parent) {\n this._parent && this._parent.removeChild(this);\n this._parent = parent;\n parent && parent._children.push(this);\n }\n\n /**\n * Returns the parent {@link DataModel} instance.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n *\n * const dt2 = dt.select(fields => fields.Origin.value === \"USA\");\n * const parentDm = dt2.getParent();\n *\n * @return {DataModel} Returns the parent DataModel instance.\n */\n getParent () {\n return this._parent;\n }\n\n /**\n * Returns the immediate child {@link DataModel} instances.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n *\n * const childDm1 = dt.select(fields => fields.Origin.value === \"USA\");\n * const childDm2 = dt.select(fields => fields.Origin.value === \"Japan\");\n * const childDm3 = dt.groupBy([\"Origin\"]);\n *\n * @return {DataModel[]} Returns the immediate child DataModel instances.\n */\n getChildren () {\n return this._children;\n }\n\n /**\n * Returns the in-between operation meta data while creating the current {@link DataModel} instance.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n * const dt2 = dt.select(fields => fields.Origin.value === \"USA\");\n * const dt3 = dt2.groupBy([\"Origin\"]);\n * const derivations = dt3.getDerivations();\n *\n * @return {Any[]} Returns the derivation meta data.\n */\n getDerivations () {\n return this._derivation;\n }\n\n /**\n * Returns the in-between operation meta data happened from root {@link DataModel} to current instance.\n *\n * @example\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'HorsePower', type: 'measure' },\n * { name: \"Origin\", type: 'dimension' }\n * ];\n *\n * const data = [\n * { Name: \"chevrolet chevelle malibu\", Horsepower: 130, Origin: \"USA\" },\n * { Name: \"citroen ds-21 pallas\", Horsepower: 115, Origin: \"Europe\" },\n * { Name: \"datsun pl510\", Horsepower: 88, Origin: \"Japan\" },\n * { Name: \"amc rebel sst\", Horsepower: 150, Origin: \"USA\"},\n * ]\n *\n * const dt = new DataModel(data, schema);\n * const dt2 = dt.select(fields => fields.Origin.value === \"USA\");\n * const dt3 = dt2.groupBy([\"Origin\"]);\n * const ancDerivations = dt3.getAncestorDerivations();\n *\n * @return {Any[]} Returns the previous derivation meta data.\n */\n getAncestorDerivations () {\n return this._ancestorDerivation;\n }\n}\n\nexport default Relation;\n","/* eslint-disable default-case */\n\nimport { FieldType, DimensionSubtype, DataFormat, FilteringMode } from './enums';\nimport {\n persistDerivations,\n getRootGroupByModel,\n propagateToAllDataModels,\n getRootDataModel,\n propagateImmutableActions,\n addToPropNamespace,\n sanitizeUnitSchema,\n splitWithSelect,\n splitWithProject,\n getNormalizedProFields\n} from './helper';\nimport { DM_DERIVATIVES, PROPAGATION } from './constants';\nimport {\n dataBuilder,\n rowDiffsetIterator,\n groupBy\n} from './operator';\nimport { createBinnedFieldData } from './operator/bucket-creator';\nimport Relation from './relation';\nimport reducerStore from './utils/reducer-store';\nimport { createFields } from './field-creator';\nimport InvalidAwareTypes from './invalid-aware-types';\nimport Value from './value';\n\n/**\n * DataModel is an in-browser representation of tabular data. It supports\n * {@link https://en.wikipedia.org/wiki/Relational_algebra | relational algebra} operators as well as generic data\n * processing opearators.\n * DataModel extends {@link Relation} class which defines all the relational algebra opreators. DataModel gives\n * definition of generic data processing operators which are not relational algebra complient.\n *\n * @public\n * @class\n * @extends Relation\n * @memberof Datamodel\n */\nclass DataModel extends Relation {\n /**\n * Creates a new DataModel instance by providing data and schema. Data could be in the form of\n * - Flat JSON\n * - DSV String\n * - 2D Array\n *\n * By default DataModel finds suitable adapter to serialize the data. DataModel also expects a\n * {@link Schema | schema} for identifying the variables present in data.\n *\n * @constructor\n * @example\n * const data = loadData('cars.csv');\n * const schema = [\n * { name: 'Name', type: 'dimension' },\n * { name: 'Miles_per_Gallon', type: 'measure', unit : 'cm', scale: '1000', numberformat: val => `${val}G`},\n * { name: 'Cylinders', type: 'dimension' },\n * { name: 'Displacement', type: 'measure' },\n * { name: 'Horsepower', type: 'measure' },\n * { name: 'Weight_in_lbs', type: 'measure' },\n * { name: 'Acceleration', type: 'measure' },\n * { name: 'Year', type: 'dimension', subtype: 'datetime', format: '%Y' },\n * { name: 'Origin', type: 'dimension' }\n * ];\n * const dm = new DataModel(data, schema, { name: 'Cars' });\n * table(dm);\n *\n * @public\n *\n * @param {Array. | string | Array.} data Input data in any of the mentioned formats\n * @param {Array.} schema Defination of the variables. Order of the variables in data and order of the\n * variables in schema has to be same.\n * @param {object} [options] Optional arguments to specify more settings regarding the creation part\n * @param {string} [options.name] Name of the datamodel instance. If no name is given an auto generated name is\n * assigned to the instance.\n * @param {string} [options.fieldSeparator=','] specify field separator type if the data is of type dsv string.\n */\n constructor (...args) {\n super(...args);\n\n this._onPropagation = [];\n }\n\n /**\n * Reducers are simple functions which reduces an array of numbers to a representative number of the set.\n * Like an array of numbers `[10, 20, 5, 15]` can be reduced to `12.5` if average / mean reducer function is\n * applied. All the measure fields in datamodel (variables in data) needs a reducer to handle aggregation.\n *\n * @public\n *\n * @return {ReducerStore} Singleton instance of {@link ReducerStore}.\n */\n static get Reducers () {\n return reducerStore;\n }\n\n /**\n * Configure null, undefined, invalid values in the source data\n *\n * @public\n *\n * @param {Object} [config] - Configuration to control how null, undefined and non-parsable values are\n * represented in DataModel.\n * @param {string} [config.undefined] - Define how an undefined value will be represented.\n * @param {string} [config.null] - Define how a null value will be represented.\n * @param {string} [config.invalid] - Define how a non-parsable value will be represented.\n */\n static configureInvalidAwareTypes (config) {\n return InvalidAwareTypes.invalidAwareVals(config);\n }\n\n /**\n * Retrieve the data attached to an instance in JSON format.\n *\n * @example\n * // DataModel instance is already prepared and assigned to dm variable\n * const data = dm.getData({\n * order: 'column',\n * formatter: {\n * origin: (val) => val === 'European Union' ? 'EU' : val;\n * }\n * });\n * console.log(data);\n *\n * @public\n *\n * @param {Object} [options] Options to control how the raw data is to be returned.\n * @param {string} [options.order='row'] Defines if data is retieved in row order or column order. Possible values\n * are `'rows'` and `'columns'`\n * @param {Function} [options.formatter=null] Formats the output data. This expects an object, where the keys are\n * the name of the variable needs to be formatted. The formatter function is called for each row passing the\n * value of the cell for a particular row as arguments. The formatter is a function in the form of\n * `function (value, rowId, schema) => { ... }`\n * Know more about {@link Fomatter}.\n *\n * @return {Array} Returns a multidimensional array of the data with schema. The return format looks like\n * ```\n * {\n * data,\n * schema\n * }\n * ```\n */\n getData (options) {\n const defOptions = {\n order: 'row',\n formatter: null,\n withUid: false,\n getAllFields: false,\n sort: []\n };\n options = Object.assign({}, defOptions, options);\n const fields = this.getPartialFieldspace().fields;\n\n const dataGenerated = dataBuilder.call(\n this,\n this.getPartialFieldspace().fields,\n this._rowDiffset,\n options.getAllFields ? fields.map(d => d.name()).join() : this._colIdentifier,\n options.sort,\n {\n columnWise: options.order === 'column',\n addUid: !!options.withUid\n }\n );\n\n if (!options.formatter) {\n return dataGenerated;\n }\n\n const { formatter } = options;\n const { data, schema, uids } = dataGenerated;\n const fieldNames = schema.map((e => e.name));\n const fmtFieldNames = Object.keys(formatter);\n const fmtFieldIdx = fmtFieldNames.reduce((acc, next) => {\n const idx = fieldNames.indexOf(next);\n if (idx !== -1) {\n acc.push([idx, formatter[next]]);\n }\n return acc;\n }, []);\n\n if (options.order === 'column') {\n fmtFieldIdx.forEach((elem) => {\n const fIdx = elem[0];\n const fmtFn = elem[1];\n\n data[fIdx].forEach((datum, datumIdx) => {\n data[fIdx][datumIdx] = fmtFn.call(\n undefined,\n datum,\n uids[datumIdx],\n schema[fIdx]\n );\n });\n });\n } else {\n data.forEach((datum, datumIdx) => {\n fmtFieldIdx.forEach((elem) => {\n const fIdx = elem[0];\n const fmtFn = elem[1];\n\n datum[fIdx] = fmtFn.call(\n undefined,\n datum[fIdx],\n uids[datumIdx],\n schema[fIdx]\n );\n });\n });\n }\n\n return dataGenerated;\n }\n\n /**\n * Returns the unique ids in an array.\n *\n * @return {Array} Returns an array of ids.\n */\n getUids () {\n const rowDiffset = this._rowDiffset;\n const ids = [];\n\n if (rowDiffset.length) {\n const diffSets = rowDiffset.split(',');\n\n diffSets.forEach((set) => {\n let [start, end] = set.split('-').map(Number);\n\n end = end !== undefined ? end : start;\n ids.push(...Array(end - start + 1).fill().map((_, idx) => start + idx));\n });\n }\n\n return ids;\n }\n /**\n * Groups the data using particular dimensions and by reducing measures. It expects a list of dimensions using which\n * it projects the datamodel and perform aggregations to reduce the duplicate tuples. Refer this\n * {@link link_to_one_example_with_group_by | document} to know the intuition behind groupBy.\n *\n * DataModel by default provides definition of few {@link reducer | Reducers}.\n * {@link ReducerStore | User defined reducers} can also be registered.\n *\n * This is the chained implementation of `groupBy`.\n * `groupBy` also supports {@link link_to_compose_groupBy | composability}\n *\n * @example\n * const groupedDM = dm.groupBy(['Year'], { horsepower: 'max' } );\n * console.log(groupedDm);\n *\n * @public\n *\n * @param {Array.} fieldsArr - Array containing the name of dimensions\n * @param {Object} [reducers={}] - A map whose key is the variable name and value is the name of the reducer. If its\n * not passed, or any variable is ommitted from the object, default aggregation function is used from the\n * schema of the variable.\n *\n * @return {DataModel} Returns a new DataModel instance after performing the groupby.\n */\n groupBy (fieldsArr, reducers = {}, config = { saveChild: true }) {\n const groupByString = `${fieldsArr.join()}`;\n let params = [this, fieldsArr, reducers];\n const newDataModel = groupBy(...params);\n\n persistDerivations(\n this,\n newDataModel,\n DM_DERIVATIVES.GROUPBY,\n { fieldsArr, groupByString, defaultReducer: reducerStore.defaultReducer() },\n reducers\n );\n\n if (config.saveChild) {\n newDataModel.setParent(this);\n } else {\n newDataModel.setParent(null);\n }\n\n return newDataModel;\n }\n\n /**\n * Performs sorting operation on the current {@link DataModel} instance according to the specified sorting details.\n * Like every other operator it doesn't mutate the current DataModel instance on which it was called, instead\n * returns a new DataModel instance containing the sorted data.\n *\n * DataModel support multi level sorting by listing the variables using which sorting needs to be performed and\n * the type of sorting `ASC` or `DESC`.\n *\n * In the following example, data is sorted by `Origin` field in `DESC` order in first level followed by another\n * level of sorting by `Acceleration` in `ASC` order.\n *\n * @example\n * // here dm is the pre-declared DataModel instance containing the data of 'cars.json' file\n * let sortedDm = dm.sort([\n * [\"Origin\", \"DESC\"]\n * [\"Acceleration\"] // Default value is ASC\n * ]);\n *\n * console.log(dm.getData());\n * console.log(sortedDm.getData());\n *\n * // Sort with a custom sorting function\n * sortedDm = dm.sort([\n * [\"Origin\", \"DESC\"]\n * [\"Acceleration\", (a, b) => a - b] // Custom sorting function\n * ]);\n *\n * console.log(dm.getData());\n * console.log(sortedDm.getData());\n *\n * @text\n * DataModel also provides another sorting mechanism out of the box where sort is applied to a variable using\n * another variable which determines the order.\n * Like the above DataModel contains three fields `Origin`, `Name` and `Acceleration`. Now, the data in this\n * model can be sorted by `Origin` field according to the average value of all `Acceleration` for a\n * particular `Origin` value.\n *\n * @example\n * // here dm is the pre-declared DataModel instance containing the data of 'cars.json' file\n * const sortedDm = dm.sort([\n * ['Origin', ['Acceleration', (a, b) => avg(...a.Acceleration) - avg(...b.Acceleration)]]\n * ]);\n *\n * console.log(dm.getData());\n * console.log(sortedDm.getData());\n *\n * @public\n *\n * @param {Array.} sortingDetails - Sorting details based on which the sorting will be performed.\n * @return {DataModel} Returns a new instance of DataModel with sorted data.\n */\n sort (sortingDetails, config = { saveChild: false }) {\n const rawData = this.getData({\n order: 'row',\n sort: sortingDetails\n });\n const header = rawData.schema.map(field => field.name);\n const dataInCSVArr = [header].concat(rawData.data);\n\n const sortedDm = new this.constructor(dataInCSVArr, rawData.schema, { dataFormat: 'DSVArr' });\n\n persistDerivations(\n this,\n sortedDm,\n DM_DERIVATIVES.SORT,\n config,\n sortingDetails\n );\n\n if (config.saveChild) {\n sortedDm.setParent(this);\n } else {\n sortedDm.setParent(null);\n }\n\n return sortedDm;\n }\n\n /**\n * Performs the serialization operation on the current {@link DataModel} instance according to the specified data\n * type. When an {@link DataModel} instance is created, it de-serializes the input data into its internal format,\n * and during its serialization process, it converts its internal data format to the specified data type and returns\n * that data regardless what type of data is used during the {@link DataModel} initialization.\n *\n * @example\n * // here dm is the pre-declared DataModel instance.\n * const csvData = dm.serialize(DataModel.DataFormat.DSV_STR, { fieldSeparator: \",\" });\n * console.log(csvData); // The csv formatted data.\n *\n * const jsonData = dm.serialize(DataModel.DataFormat.FLAT_JSON);\n * console.log(jsonData); // The json data.\n *\n * @public\n *\n * @param {string} type - The data type name for serialization.\n * @param {Object} options - The optional option object.\n * @param {string} options.fieldSeparator - The field separator character for DSV data type.\n * @return {Array|string} Returns the serialized data.\n */\n serialize (type, options) {\n type = type || this._dataFormat;\n options = Object.assign({}, { fieldSeparator: ',' }, options);\n\n const fields = this.getFieldspace().fields;\n const colData = fields.map(f => f.formattedData());\n const rowsCount = colData[0].length;\n let serializedData;\n let rowIdx;\n let colIdx;\n\n if (type === DataFormat.FLAT_JSON) {\n serializedData = [];\n for (rowIdx = 0; rowIdx < rowsCount; rowIdx++) {\n const row = {};\n for (colIdx = 0; colIdx < fields.length; colIdx++) {\n row[fields[colIdx].name()] = colData[colIdx][rowIdx];\n }\n serializedData.push(row);\n }\n } else if (type === DataFormat.DSV_STR) {\n serializedData = [fields.map(f => f.name()).join(options.fieldSeparator)];\n for (rowIdx = 0; rowIdx < rowsCount; rowIdx++) {\n const row = [];\n for (colIdx = 0; colIdx < fields.length; colIdx++) {\n row.push(colData[colIdx][rowIdx]);\n }\n serializedData.push(row.join(options.fieldSeparator));\n }\n serializedData = serializedData.join('\\n');\n } else if (type === DataFormat.DSV_ARR) {\n serializedData = [fields.map(f => f.name())];\n for (rowIdx = 0; rowIdx < rowsCount; rowIdx++) {\n const row = [];\n for (colIdx = 0; colIdx < fields.length; colIdx++) {\n row.push(colData[colIdx][rowIdx]);\n }\n serializedData.push(row);\n }\n } else {\n throw new Error(`Data type ${type} is not supported`);\n }\n\n return serializedData;\n }\n\n addField (field) {\n const fieldName = field.name();\n this._colIdentifier += `,${fieldName}`;\n const partialFieldspace = this._partialFieldspace;\n const cachedValueObjects = partialFieldspace._cachedValueObjects;\n const formattedData = field.formattedData();\n const rawData = field.partialField.data;\n\n if (!partialFieldspace.fieldsObj()[field.name()]) {\n partialFieldspace.fields.push(field);\n cachedValueObjects.forEach((obj, i) => {\n obj[field.name()] = new Value(formattedData[i], rawData[i], field);\n });\n } else {\n const fieldIndex = partialFieldspace.fields.findIndex(fieldinst => fieldinst.name() === fieldName);\n fieldIndex >= 0 && (partialFieldspace.fields[fieldIndex] = field);\n }\n\n // flush out cached namespace values on addition of new fields\n partialFieldspace._cachedFieldsObj = null;\n partialFieldspace._cachedDimension = null;\n partialFieldspace._cachedMeasure = null;\n\n this.__calculateFieldspace().calculateFieldsConfig();\n return this;\n }\n\n /**\n * Creates a new variable calculated from existing variables. This method expects the definition of the newly created\n * variable and a function which resolves the value of the new variable from existing variables.\n *\n * Can create a new measure based on existing variables:\n * @example\n * // DataModel already prepared and assigned to dm variable;\n * const newDm = dataModel.calculateVariable({\n * name: 'powerToWeight',\n * type: 'measure'\n * }, ['horsepower', 'weight_in_lbs', (hp, weight) => hp / weight ]);\n *\n *\n * Can create a new dimension based on existing variables:\n * @example\n * // DataModel already prepared and assigned to dm variable;\n * const child = dataModel.calculateVariable(\n * {\n * name: 'Efficiency',\n * type: 'dimension'\n * }, ['horsepower', (hp) => {\n * if (hp < 80) { return 'low'; },\n * else if (hp < 120) { return 'moderate'; }\n * else { return 'high' }\n * }]);\n *\n * @public\n *\n * @param {Object} schema - The schema of newly defined variable.\n * @param {Array.} dependency - An array containing the dependency variable names and a resolver\n * function as the last element.\n * @param {Object} config - An optional config object.\n * @param {boolean} [config.saveChild] - Whether the newly created DataModel will be a child.\n * @param {boolean} [config.replaceVar] - Whether the newly created variable will replace the existing variable.\n * @return {DataModel} Returns an instance of DataModel with the new field.\n */\n calculateVariable (schema, dependency, config) {\n schema = sanitizeUnitSchema(schema);\n config = Object.assign({}, { saveChild: true, replaceVar: false }, config);\n\n const fieldsConfig = this.getFieldsConfig();\n const depVars = dependency.slice(0, dependency.length - 1);\n const retrieveFn = dependency[dependency.length - 1];\n\n if (fieldsConfig[schema.name] && !config.replaceVar) {\n throw new Error(`${schema.name} field already exists in datamodel`);\n }\n\n const depFieldIndices = depVars.map((field) => {\n const fieldSpec = fieldsConfig[field];\n if (!fieldSpec) {\n // @todo dont throw error here, use warning in production mode\n throw new Error(`${field} is not a valid column name.`);\n }\n return fieldSpec.index;\n });\n\n const clone = this.clone(config.saveChild);\n\n const fs = clone.getFieldspace().fields;\n const suppliedFields = depFieldIndices.map(idx => fs[idx]);\n\n let cachedStore = {};\n let cloneProvider = () => this.detachedRoot();\n\n const computedValues = [];\n rowDiffsetIterator(clone._rowDiffset, (i) => {\n const fieldsData = suppliedFields.map(field => field.partialField.data[i]);\n computedValues[i] = retrieveFn(...fieldsData, i, cloneProvider, cachedStore);\n });\n const [field] = createFields([computedValues], [schema], [schema.name]);\n clone.addField(field);\n\n persistDerivations(\n this,\n clone,\n DM_DERIVATIVES.CAL_VAR,\n { config: schema, fields: depVars },\n retrieveFn\n );\n\n return clone;\n }\n\n /**\n * Propagates changes across all the connected DataModel instances.\n *\n * @param {Array} identifiers - A list of identifiers that were interacted with.\n * @param {Object} payload - The interaction specific details.\n *\n * @return {DataModel} DataModel instance.\n */\n propagate (identifiers, config = {}, addToNameSpace, propConfig = {}) {\n const isMutableAction = config.isMutableAction;\n const propagationSourceId = config.sourceId;\n const payload = config.payload;\n const rootModel = getRootDataModel(this);\n const propagationNameSpace = rootModel._propagationNameSpace;\n const rootGroupByModel = getRootGroupByModel(this);\n const rootModels = {\n groupByModel: rootGroupByModel,\n model: rootModel\n };\n\n addToNameSpace && addToPropNamespace(propagationNameSpace, config, this);\n propagateToAllDataModels(identifiers, rootModels, { propagationNameSpace, sourceId: propagationSourceId },\n Object.assign({\n payload\n }, config));\n\n if (isMutableAction) {\n propagateImmutableActions(propagationNameSpace, rootModels, {\n config,\n propConfig\n }, this);\n }\n\n return this;\n }\n\n /**\n * Associates a callback with an event name.\n *\n * @param {string} eventName - The name of the event.\n * @param {Function} callback - The callback to invoke.\n * @return {DataModel} Returns this current DataModel instance itself.\n */\n on (eventName, callback) {\n switch (eventName) {\n case PROPAGATION:\n this._onPropagation.push(callback);\n break;\n }\n return this;\n }\n\n /**\n * Unsubscribes the callbacks for the provided event name.\n *\n * @param {string} eventName - The name of the event to unsubscribe.\n * @return {DataModel} Returns the current DataModel instance itself.\n */\n unsubscribe (eventName) {\n switch (eventName) {\n case PROPAGATION:\n this._onPropagation = [];\n break;\n\n }\n return this;\n }\n\n /**\n * This method is used to invoke the method associated with propagation.\n *\n * @param {Object} payload The interaction payload.\n * @param {DataModel} identifiers The propagated DataModel.\n * @memberof DataModel\n */\n handlePropagation (propModel, payload) {\n let propListeners = this._onPropagation;\n propListeners.forEach(fn => fn.call(this, propModel, payload));\n }\n\n /**\n * Performs the binning operation on a measure field based on the binning configuration. Binning means discretizing\n * values of a measure. Binning configuration contains an array; subsequent values from the array marks the boundary\n * of buckets in [inclusive, exclusive) range format. This operation does not mutate the subject measure field,\n * instead, it creates a new field (variable) of type dimension and subtype binned.\n *\n * Binning can be configured by\n * - providing custom bin configuration with non-uniform buckets,\n * - providing bins count,\n * - providing each bin size,\n *\n * When custom `buckets` are provided as part of binning configuration:\n * @example\n * // DataModel already prepared and assigned to dm variable\n * const config = { name: 'binnedHP', buckets: [30, 80, 100, 110] }\n * const binnedDM = dataModel.bin('horsepower', config);\n *\n * @text\n * When `binsCount` is defined as part of binning configuration:\n * @example\n * // DataModel already prepared and assigned to dm variable\n * const config = { name: 'binnedHP', binsCount: 5, start: 0, end: 100 }\n * const binDM = dataModel.bin('horsepower', config);\n *\n * @text\n * When `binSize` is defined as part of binning configuration:\n * @example\n * // DataModel already prepared and assigned to dm variable\n * const config = { name: 'binnedHorsepower', binSize: 20, start: 5}\n * const binDM = dataModel.bin('horsepower', config);\n *\n * @public\n *\n * @param {string} measureFieldName - The name of the target measure field.\n * @param {Object} config - The config object.\n * @param {string} [config.name] - The name of the new field which will be created.\n * @param {string} [config.buckets] - An array containing the bucket ranges.\n * @param {string} [config.binSize] - The size of each bin. It is ignored when buckets are given.\n * @param {string} [config.binsCount] - The total number of bins to generate. It is ignored when buckets are given.\n * @param {string} [config.start] - The start value of the bucket ranges. It is ignored when buckets are given.\n * @param {string} [config.end] - The end value of the bucket ranges. It is ignored when buckets are given.\n * @return {DataModel} Returns a new {@link DataModel} instance with the new field.\n */\n bin (measureFieldName, config) {\n const fieldsConfig = this.getFieldsConfig();\n\n if (!fieldsConfig[measureFieldName]) {\n throw new Error(`Field ${measureFieldName} doesn't exist`);\n }\n\n const binFieldName = config.name || `${measureFieldName}_binned`;\n\n if (fieldsConfig[binFieldName]) {\n throw new Error(`Field ${binFieldName} already exists`);\n }\n\n const measureField = this.getFieldspace().fieldsObj()[measureFieldName];\n const { binnedData, bins } = createBinnedFieldData(measureField, this._rowDiffset, config);\n\n const binField = createFields([binnedData], [\n {\n name: binFieldName,\n type: FieldType.DIMENSION,\n subtype: DimensionSubtype.BINNED,\n bins\n }], [binFieldName])[0];\n\n const clone = this.clone(config.saveChild);\n clone.addField(binField);\n\n persistDerivations(\n this,\n clone,\n DM_DERIVATIVES.BIN,\n { measureFieldName, config, binFieldName },\n null\n );\n\n return clone;\n }\n\n /**\n * Creates a new {@link DataModel} instance with completely detached root from current {@link DataModel} instance,\n * the new {@link DataModel} instance has no parent-children relationship with the current one, but has same data as\n * the current one.\n * This API is useful when a completely different {@link DataModel} but with same data as the current instance is\n * needed.\n *\n * @example\n * const dm = new DataModel(data, schema);\n * const detachedDm = dm.detachedRoot();\n *\n * // has different namespace\n * console.log(dm.getPartialFieldspace().name);\n * console.log(detachedDm.getPartialFieldspace().name);\n *\n * // has same data\n * console.log(dm.getData());\n * console.log(detachedDm.getData());\n *\n * @public\n *\n * @return {DataModel} Returns a detached {@link DataModel} instance.\n */\n detachedRoot () {\n const data = this.serialize(DataFormat.FLAT_JSON);\n const schema = this.getSchema();\n\n return new DataModel(data, schema);\n }\n\n /**\n * Creates a set of new {@link DataModel} instances by splitting the set of rows in the source {@link DataModel}\n * instance based on a set of dimensions.\n *\n * For each unique dimensional value, a new split is created which creates a unique {@link DataModel} instance for\n * that split\n *\n * If multiple dimensions are provided, it splits the source {@link DataModel} instance with all possible\n * combinations of the dimensional values for all the dimensions provided\n *\n * Additionally, it also accepts a predicate function to reduce the set of rows provided. A\n * {@link link_to_selection | Selection} is performed on all the split {@link DataModel} instances based on\n * the predicate function\n *\n * @example\n * // without predicate function:\n * const splitDt = dt.splitByRow(['Origin'])\n * console.log(splitDt));\n * // This should give three unique DataModel instances, one each having rows only for 'USA',\n * // 'Europe' and 'Japan' respectively\n *\n * @example\n * // without predicate function:\n * const splitDtMulti = dt.splitByRow(['Origin', 'Cylinders'])\n * console.log(splitDtMulti));\n * // This should give DataModel instances for all unique combinations of Origin and Cylinder values\n *\n * @example\n * // with predicate function:\n * const splitWithPredDt = dt.select(['Origin'], fields => fields.Origin.value === \"USA\")\n * console.log(splitWithPredDt);\n * // This should not include the DataModel for the Origin : 'USA'\n *\n *\n * @public\n *\n * @param {Array} dimensionArr - Set of dimensions based on which the split should occur\n * @param {Object} config - The configuration object\n * @param {string} [config.saveChild] - Configuration to save child or not\n * @param {string}[config.mode=FilteringMode.NORMAL] -The mode of the selection.\n * @return {Array} Returns the new DataModel instances after operation.\n */\n splitByRow (dimensionArr, reducerFn, config) {\n const fieldsConfig = this.getFieldsConfig();\n\n dimensionArr.forEach((fieldName) => {\n if (!fieldsConfig[fieldName]) {\n throw new Error(`Field ${fieldName} doesn't exist in the schema`);\n }\n });\n\n const defConfig = {\n mode: FilteringMode.NORMAL,\n saveChild: true\n };\n\n config = Object.assign({}, defConfig, config);\n\n return splitWithSelect(this, dimensionArr, reducerFn, config);\n }\n\n /**\n * Creates a set of new {@link DataModel} instances by splitting the set of fields in the source {@link DataModel}\n * instance based on a set of common and unique field names provided.\n *\n * Each DataModel created contains a set of fields which are common to all and a set of unique fields.\n * It also accepts configurations such as saveChild and mode(inverse or normal) to include/exclude the respective\n * fields\n *\n * @example\n * // without predicate function:\n * const splitDt = dt.splitByColumn( [['Acceleration'], ['Horsepower']], ['Origin'])\n * console.log(splitDt));\n * // This should give two unique DataModel instances, both having the field 'Origin' and\n * // one each having 'Acceleration' and 'Horsepower' fields respectively\n *\n * @example\n * // without predicate function:\n * const splitDtInv = dt.splitByColumn( [['Acceleration'], ['Horsepower'],['Origin', 'Cylinders'],\n * {mode: 'inverse'})\n * console.log(splitDtInv));\n * // This should give DataModel instances in the following way:\n * // All DataModel Instances do not have the fields 'Origin' and 'Cylinders'\n * // One DataModel Instance has rest of the fields except 'Acceleration' and the other DataModel instance\n * // has rest of the fields except 'Horsepower'\n *\n *\n *\n * @public\n *\n * @param {Array} uniqueFields - Set of unique fields included in each datamModel instance\n * @param {Array} commonFields - Set of common fields included in all datamModel instances\n * @param {Object} config - The configuration object\n * @param {string} [config.saveChild] - Configuration to save child or not\n * @param {string}[config.mode=FilteringMode.NORMAL] -The mode of the selection.\n * @return {Array} Returns the new DataModel instances after operation.\n */\n splitByColumn (uniqueFields = [], commonFields = [], config) {\n const defConfig = {\n mode: FilteringMode.NORMAL,\n saveChild: true\n };\n const fieldConfig = this.getFieldsConfig();\n const allFields = Object.keys(fieldConfig);\n const normalizedProjFieldSets = [[commonFields]];\n\n config = Object.assign({}, defConfig, config);\n uniqueFields = uniqueFields.length ? uniqueFields : [[]];\n\n\n uniqueFields.forEach((fieldSet, i) => {\n normalizedProjFieldSets[i] = getNormalizedProFields(\n [...fieldSet, ...commonFields],\n allFields,\n fieldConfig);\n });\n\n return splitWithProject(this, normalizedProjFieldSets, config, allFields);\n }\n\n\n}\n\nexport default DataModel;\n","import { fnList } from '../operator/group-by-function';\n\nexport const { sum, avg, min, max, first, last, count, std: sd } = fnList;\n","import DataModel from './datamodel';\nimport {\n compose,\n bin,\n select,\n project,\n groupby as groupBy,\n calculateVariable,\n sort,\n crossProduct,\n difference,\n naturalJoin,\n leftOuterJoin,\n rightOuterJoin,\n fullOuterJoin,\n union\n} from './operator';\nimport * as Stats from './stats';\nimport * as enums from './enums';\nimport { DateTimeFormatter } from './utils';\nimport { DataFormat, FilteringMode, DM_DERIVATIVES } from './constants';\nimport InvalidAwareTypes from './invalid-aware-types';\nimport pkg from '../package.json';\n\nconst Operators = {\n compose,\n bin,\n select,\n project,\n groupBy,\n calculateVariable,\n sort,\n crossProduct,\n difference,\n naturalJoin,\n leftOuterJoin,\n rightOuterJoin,\n fullOuterJoin,\n union\n};\n\nconst version = pkg.version;\nObject.assign(DataModel, {\n Operators,\n Stats,\n DM_DERIVATIVES,\n DateTimeFormatter,\n DataFormat,\n FilteringMode,\n InvalidAwareTypes,\n version\n}, enums);\n\nexport default DataModel;\n","import { persistDerivations } from '../helper';\nimport { DM_DERIVATIVES } from '../constants';\n\n/**\n * DataModel's opearators are exposed as composable functional operators as well as chainable operators. Chainable\n * operators are called on the instances of {@link Datamodel} and {@link Relation} class.\n *\n * Those same operators can be used as composable operators from `DataModel.Operators` namespace.\n *\n * All these operators have similar behaviour. All these operators when called with the argument returns a function\n * which expects a DataModel instance.\n *\n * @public\n * @module Operators\n * @namespace DataModel\n */\n\n/**\n * This is functional version of selection operator. {@link link_to_selection | Selection} is a row filtering operation.\n * It takes {@link SelectionPredicate | predicate} for filtering criteria and returns a function.\n * The returned function is called with the DataModel instance on which the action needs to be performed.\n *\n * {@link SelectionPredicate} is a function which returns a boolean value. For selection opearation the selection\n * function is called for each row of DataModel instance with the current row passed as argument.\n *\n * After executing {@link SelectionPredicate} the rows are labeled as either an entry of selection set or an entry\n * of rejection set.\n *\n * {@link FilteringMode} operates on the selection and rejection set to determine which one would reflect in the\n * resulatant datamodel.\n *\n * @warning\n * [Warn] Selection and rejection set is only a logical idea for concept explanation purpose.\n *\n * @error\n * [Error] `FilteringMode.ALL` is not a valid working mode for functional version of `select`. Its only avialable on the\n * chained version.\n *\n * @example\n * const select = DataModel.Operators.select;\n * usaCarsFn = select(fields => fields.Origin.value === 'USA');\n * usaCarsDm = usaCarsFn(dm);\n * console.log(usaCarsDm);\n *\n * @public\n * @namespace DataModel\n * @module Operators\n *\n * @param {SelectionPredicate} selectFn - Predicate funciton which is called for each row with the current row\n * ```\n * function (row, i) { ... }\n * ```\n * @param {Object} [config] - The configuration object to control the inclusion exclusion of a row in resultant\n * DataModel instance\n * @param {FilteringMode} [config.mode=FilteringMode.NORMAL] - The mode of the selection\n *\n * @return {PreparatorFunction} Function which expects an instance of DataModel on which the operator needs to be\n * applied.\n */\nexport const select = (...args) => dm => dm.select(...args);\n\n/**\n * This is functional version of projection operator. {@link link_to_projection | Projection} is a column filtering\n * operation.It expects list of fields name and either include those or exclude those based on {@link FilteringMode} on\n * the resultant variable.It returns a function which is called with the DataModel instance on which the action needs\n * to be performed.\n *\n * Projection expects array of fields name based on which it creates the selection and rejection set. All the field\n * whose name is present in array goes in selection set and rest of the fields goes in rejection set.\n *\n * {@link FilteringMode} operates on the selection and rejection set to determine which one would reflect in the\n * resulatant datamodel.\n *\n * @warning\n * Selection and rejection set is only a logical idea for concept explanation purpose.\n *\n * @error\n * `FilteringMode.ALL` is not a valid working mode for functional version of `select`. Its only avialable on the\n * chained version.\n *\n * @public\n * @namespace DataModel\n * @module Operators\n *\n * @param {Array.} projField - An array of column names in string or regular expression.\n * @param {Object} [config] - An optional config to control the creation of new DataModel\n * @param {FilteringMode} [config.mode=FilteringMode.NORMAL] - Mode of the projection\n *\n * @return {PreparatorFunction} Function which expects an instance of DataModel on which the operator needs to be\n * applied.\n */\nexport const project = (...args) => dm => dm.project(...args);\n\n/**\n * This is functional version of binnig operator. Binning happens on a measure field based on a binning configuration.\n * Binning in DataModel does not aggregate the number of rows present in DataModel instance after binning, it just adds\n * a new field with the binned value. Refer binning {@link example_of_binning | example} to have a intuition of what\n * binning is and the use case.\n *\n * Binning can be configured by\n * - providing custom bin configuration with non uniform buckets\n * - providing bin count\n * - providing each bin size\n *\n * When custom buckets are provided as part of binning configuration\n * @example\n * // DataModel already prepared and assigned to dm vairable\n * const buckets = {\n * start: 30\n * stops: [80, 100, 110]\n * };\n * const config = { buckets, name: 'binnedHP' }\n * const binFn = bin('horsepower', config);\n * const binnedDm = binFn(dm);\n *\n * @text\n * When `binCount` is defined as part of binning configuration\n * @example\n * // DataModel already prepared and assigned to dm vairable\n * const config = { binCount: 5, name: 'binnedHP' }\n * const binFn = bin('horsepower', config);\n * const binnedDm = binFn(Dm);\n *\n * @text\n * When `binSize` is defined as part of binning configuration\n * @example\n * // DataModel already prepared and assigned to dm vairable\n * const config = { binSize: 200, name: 'binnedHorsepower' }\n * const binnedDm = dataModel.bin('horsepower', config);\n * const binnedDm = binFn(Dm);\n *\n * @public\n * @namespace DataModel\n * @module Operators\n *\n * @param {String} name Name of measure which will be used to create bin\n * @param {Object} config Config required for bin creation\n * @param {Array.} config.bucketObj.stops Defination of bucket ranges. Two subsequent number from arrays\n * are picked and a range is created. The first number from range is inclusive and the second number from range\n * is exclusive.\n * @param {Number} [config.bucketObj.startAt] Force the start of the bin from a particular number.\n * If not mentioned, the start of the bin or the lower domain of the data if stops is not mentioned, else its\n * the first value of the stop.\n * @param {Number} config.binSize Bucket size for each bin\n * @param {Number} config.binCount Number of bins which will be created\n * @param {String} config.name Name of the new binned field to be created\n *\n * @return {PreparatorFunction} Function which expects an instance of DataModel on which the operator needs to be\n * applied.\n */\nexport const bin = (...args) => dm => dm.bin(...args);\n\n/**\n * This is functional version of `groupBy` operator.Groups the data using particular dimensions and by reducing\n * measures. It expects a list of dimensions using which it projects the datamodel and perform aggregations to reduce\n * the duplicate tuples. Refer this {@link link_to_one_example_with_group_by | document} to know the intuition behind\n * groupBy.\n *\n * DataModel by default provides definition of few {@link reducer | Reducers}.\n * {@link ReducerStore | User defined reducers} can also be registered.\n *\n * This is the chained implementation of `groupBy`.\n * `groupBy` also supports {@link link_to_compose_groupBy | composability}\n *\n * @example\n * const groupBy = DataModel.Operators.groupBy;\n * const groupedFn = groupBy(['Year'], { horsepower: 'max' } );\n * groupedDM = groupByFn(dm);\n *\n * @public\n *\n * @param {Array.} fieldsArr - Array containing the name of dimensions\n * @param {Object} [reducers={}] - A map whose key is the variable name and value is the name of the reducer. If its\n * not passed, or any variable is ommitted from the object, default aggregation function is used from the\n * schema of the variable.\n *\n * @return {PreparatorFunction} Function which expects an instance of DataModel on which the operator needs to be\n * applied.\n */\nexport const groupBy = (...args) => dm => dm.groupBy(...args);\n\n/**\n * Enables composing operators to run multiple operations and save group of operataion as named opration on a DataModel.\n * The resulting DataModel will be the result of all the operation provided. The operations provided will be executed in\n * a serial manner ie. result of one operation will be the input for the next operations (like pipe operator in unix).\n *\n * Suported operations in compose are\n * - `select`\n * - `project`\n * - `groupBy`\n * - `bin`\n * - `compose`\n *\n * @example\n * const compose = DataModel.Operators.compose;\n * const select = DataModel.Operators.select;\n * const project = DataModel.Operators.project;\n *\n * let composedFn = compose(\n * select(fields => fields.netprofit.value <= 15),\n * project(['netprofit', 'netsales']));\n *\n * const dataModel = new DataModel(data1, schema1);\n *\n * let composedDm = composedFn(dataModel);\n *\n * @public\n * @namespace DataModel\n * @module Operators\n *\n * @param {Array.} operators: An array of operation that will be applied on the\n * datatable.\n *\n * @returns {DataModel} Instance of resultant DataModel\n */\nexport const compose = (...operations) =>\n (dm, config = { saveChild: true }) => {\n let currentDM = dm;\n let firstChild;\n const derivations = [];\n\n operations.forEach((operation) => {\n currentDM = operation(currentDM);\n derivations.push(...currentDM._derivation);\n if (!firstChild) {\n firstChild = currentDM;\n }\n });\n\n if (firstChild && firstChild !== currentDM) {\n firstChild.dispose();\n }\n\n // reset all ancestorDerivation saved in-between compose\n currentDM._ancestorDerivation = [];\n persistDerivations(\n dm,\n currentDM,\n DM_DERIVATIVES.COMPOSE,\n null,\n derivations\n );\n\n if (config.saveChild) {\n currentDM.setParent(dm);\n } else {\n currentDM.setParent(null);\n }\n\n return currentDM;\n };\n","/**\n * Wrapper on calculateVariable() method of DataModel to behave\n * the pure-function functionality.\n *\n * @param {Array} args - The argument list.\n * @return {any} Returns the returned value of calling function.\n */\nexport const calculateVariable = (...args) => dm => dm.calculateVariable(...args);\n\n/**\n * Wrapper on sort() method of DataModel to behave\n * the pure-function functionality.\n *\n * @param {Array} args - The argument list.\n * @return {any} Returns the returned value of calling function.\n */\nexport const sort = (...args) => dm => dm.sort(...args);\n","import { crossProduct } from './cross-product';\nimport { naturalJoinFilter } from './natural-join-filter-function';\n\nexport function naturalJoin (dataModel1, dataModel2) {\n return crossProduct(dataModel1, dataModel2, naturalJoinFilter(dataModel1, dataModel2), true);\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/example/index.html b/example/index.html index 2cd79fa..d2d791d 100644 --- a/example/index.html +++ b/example/index.html @@ -12,8 +12,8 @@ - - + + \ No newline at end of file diff --git a/example/samples/example3.js b/example/samples/example3.js index 5ad1de8..67393ce 100644 --- a/example/samples/example3.js +++ b/example/samples/example3.js @@ -1,145 +1,151 @@ -/* eslint-disable */ - -d3.json('../data/cars.json', (data) => { - let jsonData = data; - const schema = [{ - name: 'Name', - type: 'dimension' +const data = [ + { + "xvalue": -19800000, + "xvalue0": 63052200000, + "xdim": -19800000, + "yvalue": undefined, + }, + { + "xvalue": 63052200000, + "xvalue0": 126210600000, + "xdim": 63052200000 + }, + { + "xvalue": 126210600000, + "xvalue0": 189282600000, + "xdim": 126210600000 }, { - name: 'birthday', - type: 'dimension', - subtype: 'temporal', - format: '%Y-%m-%d' + "xvalue": 189282600000, + "xvalue0": 252441000000, + "xdim": 189282600000 }, { - name: 'roll', - type: 'measure', - defAggFn: "avg", - as: "roll2" + "xvalue": 252441000000, + "xvalue0": 315513000000, + "xdim": 252441000000 + }, + { + "xvalue": 315513000000, + "xvalue0": 378671400000, + "xdim": 315513000000 + }, + { + "xvalue": 378671400000, + "xdim": 378671400000 } -]; + ] -const data = [ +const schema = [ + { + "name": "yvalue", + "type": "measure" + }, + { + "name": "xvalue", + "type": "measure" + }, { - name: 'Rousan', - birthday: '1995-07-05', - roll: 2 + "name": "yvalue0", + "type": "measure" }, { - name: 'Miles_per_Gallon', - type: 'measure' + "name": "xvalue0", + "type": "measure" }, + { + "name": "xdim", + "type": "dimension", + "subtype": "temporal" + }, + { + "name": "ydim", + "type": "dimension", + "subtype": "temporal" + } + ] +window.a = new DataModel(data, schema); + +const jsonData1 = [ + { + "yvalue": 0, + "yvalue0": 50, + "ydim": 0 + }, { - name: 'Displacement', - type: 'measure' + "yvalue": 50, + "yvalue0": 100, + "ydim": 50 }, { - name: 'Horsepower', - type: 'measure' + "yvalue": 100, + "yvalue0": 150, + "ydim": 100 }, { - name: 'Weight_in_lbs', - type: 'measure' + "yvalue": 150, + "yvalue0": 200, + "ydim": 150 }, { - name: 'Acceleration', - type: 'measure' + "yvalue": 200, + "yvalue0": 250, + "ydim": 200 }, { - name: 'Origin', - type: 'dimension' + "yvalue": 250, + "yvalue0": 300, + "ydim": 250 }, { - name: 'Akash', - birthday: '1994-01-03', - roll: 120 + "yvalue": 300, + "yvalue0": 350, + "ydim": 300 }, { - name: 'Rousan', - birthday: '1995-07-06', - roll: 93 + "yvalue": 350, + "yvalue0": 400, + "ydim": 350 + }, + { + "yvalue": 400, + "yvalue0": 450, + "ydim": 400 + }, + { + "yvalue": 450, + "ydim": 450 } -]; - - -const dm = new DataModel(data, schema); -const dm2 = dm.project(["name", "roll"]); -// const schema = [ -// { name: 'Name', type: 'dimension' }, -// { name: 'HorsePower', type: 'measure' }, -// { name: 'Origin', type: 'dimension' } -// ]; -// const data = [ -// { Name: 'chevrolet chevelle malibu', Horsepower: 130, Origin: 'USA' }, -// { Name: 'citroen ds-21 pallas', Horsepower: 115, Origin: 'Europe' }, -// { Name: 'datsun pl510', Horsepower: 88, Origin: 'Japan' }, -// { Name: 'amc rebel sst', Horsepower: 150, Origin: 'USA' }, -// ]; -// const dt = new DataModel(schema, data); - -// const dt2 = dt.select(fields => fields.Origin.value === 'USA'); - -// const selectedDm = dm.select(fields => fields.roll.value > 10 || fields.roll.value < 0); - - - -// debugger; - -// const groupedDm = dm.groupBy(["name"], { -// roll: (vals, cloneProvider, store) => { -// if (!store.clonedDm) { -// store.clonedDm = cloneProvider(); -// } -// if (!store.avgRoll) { -// store.avgRoll = store.clonedDm.groupBy([""], { roll: "avg" }).getData().data[0][0]; -// } - -// return DataModel.Stats.avg(vals) - store.avgRoll; -// } -// }); -// const calDm = dm.calculateVariable({ -// name: "abc", -// type: "measure" -// }, ["roll", (roll, i, cloneProvider, store) => { -// if (!store.clonedDm) { -// store.clonedDm = cloneProvider(); -// } -// if (!store.avgRoll) { -// store.avgRoll = store.clonedDm.groupBy([""], {roll: "avg"}).getData().data[0][0]; -// } - -// return store.avgRoll - roll; -// }]); - -// const DataModel = window.DataModel; - -// const data1 = [ -// { profit: 10, sales: 20, city: 'a' }, -// { profit: 15, sales: 25, city: 'b' }, -// ]; -// const schema1 = [ -// { name: 'profit', type: 'measure' }, -// { name: 'sales', type: 'measure' }, -// { name: 'city', type: 'dimension' }, -// ]; -// const data2 = [ -// { population: 200, city: 'a' }, -// { population: 250, city: 'b' }, -// ]; -// const schema2 = [ -// { name: 'population', type: 'measure' }, -// { name: 'city', type: 'dimension' }, -// ]; -// const dataModel1 = new DataModel(data1, schema1, { name: 'ModelA' }); -// const dataModel2 = new DataModel(data2, schema2, { name: 'ModelB' }); + ]; - let rootData = new DataModel(jsonData, schema); - let dm = rootData.project(["Origin", "Acceleration"]); - let dm5 = DataModel.Operators.compose( - DataModel.Operators.groupBy(["Origin"]), - DataModel.Operators.select(f => f.Acceleration.value > 1000) - )(dm); -}); +const schema1 = [ + { + "name": "yvalue", + "type": "measure" + }, + { + "name": "xvalue", + "type": "measure" + }, + { + "name": "yvalue0", + "type": "measure" + }, + { + "name": "xvalue0", + "type": "measure" + }, + { + "name": "xdim", + "type": "dimension", + "subtype": "categorical" + }, + { + "name": "ydim", + "type": "dimension", + "subtype": "categorical" + } + ]; + window.b = new DataModel(jsonData1, schema1); \ No newline at end of file diff --git a/example/samples/example4.js b/example/samples/example4.js index 471f457..723d8cf 100644 --- a/example/samples/example4.js +++ b/example/samples/example4.js @@ -1,57 +1,66 @@ /* eslint-disable */ d3.json('./data/cars.json', (data) => { - const jsonData = data, - schema = [ - { - "name": "Name", - "type": "dimension" - }, - { - "name": "Maker", - "type": "dimension" - }, - { - "name": "Miles_per_Gallon", - "type": "measure", - "defAggFn": "avg" - }, - { - "name": "Displacement", - "type": "measure", - "subtype": "continuous", - "defAggFn": "max" - }, - { - "name": "Horsepower", - "type": "measure", - "defAggFn": "avg" - }, - { - "name": "Weight_in_lbs", - "type": "measure", - "defAggFn": "min" - }, - { - "name": "Acceleration", - "type": "measure", - "defAggFn": "avg" - }, - { - "name": "Origin", - "type": "dimension" - }, - { - "name": "Cylinders", - "type": "dimension" - }, - { - "name": "Year", - "type": "dimension", - "subtype": "temporal", - "format": "%Y-%m-%d" - } - ] + const schema = [ + { + "name": "Name", + "type": "dimension" + }, + { + "name": "Maker", + "type": "dimension" + }, + { + "name": "Miles_per_Gallon", + "type": "measure", + "defAggFn": "avg" + }, + { + "name": "Displacement", + "type": "measure", + "subtype": "continuous", + "defAggFn": "max" + }, + { + "name": "Horsepower", + "type": "measure", + "defAggFn": "avg" + }, + { + "name": "Weight_in_lbs", + "type": "measure", + "defAggFn": "min" + }, + { + "name": "Acceleration", + "type": "measure", + "defAggFn": "avg", + "numberFormat": (val) => `$${val}` + }, + { + "name": "Origin", + "type": "dimension" + }, + { + "name": "Cylinders", + "type": "dimension" + }, + { + "name": "Year", + "type": "dimension", + "subtype": "temporal", + "format": "%Y-%m-%d" + } + ]; - dm = new DataModel(jsonData, schema); + const dm = new DataModel(data, schema); + const selectedDateParsed = dm.select(fields => { + return fields.Year.value === '1970-01-01'; + }); + + const selectedDateRaw = dm.select(fields => fields.Year.internalValue === -19800000); + const newField = dm.calculateVariable({ + name: 'newField', + type: 'measure' + }, ['Horsepower', 'Weight_in_lbs', (hp, weight) => hp / weight ]); }); \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js index 235f1da..c44663c 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -6,6 +6,7 @@ module.exports = function (config) { 'test.webpack.js', ], webpack: { + mode: 'development', devtool: 'inline-source-map', module: { rules: [ diff --git a/package.json b/package.json index c723642..bdb7220 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "datamodel", "description": "Relational algebra compliant in-memory tabular data store", "homepage": "https://github.com/chartshq/datamodel", - "version": "2.2.1", + "version": "2.2.2", "license": "MIT", "main": "dist/datamodel.js", "keywords": [ @@ -38,6 +38,14 @@ { "name": "Ujjal Kumar Dutta", "email": "duttaujjalkumar@live.com" + }, + { + "name": "Ranajit Banerjee", + "email": "ranajit.113124@gmail.com" + }, + { + "name": "Adarsh Lilha", + "email": "adarshlilha@gmail.com" } ], "dependencies": { diff --git a/src/converter/auto-resolver.js b/src/converter/auto-resolver.js index 2e56e1b..2dc6ee2 100644 --- a/src/converter/auto-resolver.js +++ b/src/converter/auto-resolver.js @@ -10,7 +10,7 @@ import { detectDataFormat } from '../utils'; * @param {Object} options - An optional config specific to data format. * @return {Array.} Returns an array of headers and column major data. */ -function Auto (data, options) { +function Auto (data, schema, options) { const converters = { FlatJSON, DSVStr, DSVArr }; const dataFormat = detectDataFormat(data); @@ -18,7 +18,7 @@ function Auto (data, options) { throw new Error('Couldn\'t detect the data format'); } - return converters[dataFormat](data, options); + return converters[dataFormat](data, schema, options); } export default Auto; diff --git a/src/converter/auto-resolver.spec.js b/src/converter/auto-resolver.spec.js index a2e223a..de6f44c 100644 --- a/src/converter/auto-resolver.spec.js +++ b/src/converter/auto-resolver.spec.js @@ -1,10 +1,31 @@ -/* global describe, it */ +/* global describe, it, beforeEach */ /* eslint-disable no-unused-expressions */ import { expect } from 'chai'; import Auto from './auto-resolver'; describe('Auto Converter', () => { + let schema; + beforeEach(() => { + schema = [ + { + name: 'a', + type: 'measure', + subtype: 'continuous' + }, + { + name: 'b', + type: 'measure', + subtype: 'continuous' + }, + { + name: 'c', + type: 'measure', + subtype: 'continuous' + } + ]; + }); + describe('#Auto', () => { it('should detect the JSON data', () => { const data = [ @@ -24,13 +45,13 @@ describe('Auto Converter', () => { c: 9 } ]; - const emptyData = []; - let parsedData = Auto(data); + const emptyData = []; + let parsedData = Auto(data, schema); let expected = [['a', 'b', 'c'], [[1, 4, 7], [2, 5, 8], [3, 6, 9]]]; expect(parsedData).to.deep.equal(expected); - parsedData = Auto(emptyData); + parsedData = Auto(emptyData, []); expected = [[], []]; expect(parsedData).to.deep.equal(expected); }); @@ -42,7 +63,7 @@ describe('Auto Converter', () => { [4, 5, 6], [7, 8, 9] ]; - let parsedData = Auto(data); + let parsedData = Auto(data, schema); let expected = [['a', 'b', 'c'], [[1, 4, 7], [2, 5, 8], [3, 6, 9]]]; expect(parsedData).to.deep.equal(expected); @@ -51,26 +72,26 @@ describe('Auto Converter', () => { [4, 5, 6], [7, 8, 9] ]; - parsedData = Auto(data, { firstRowHeader: false }); + parsedData = Auto(data, [], { firstRowHeader: false }); expected = [[], [[1, 4, 7], [2, 5, 8], [3, 6, 9]]]; expect(parsedData).to.deep.equal(expected); }); it('should detect the DSV string data', () => { let data = 'a,b,c\n1,2,3\n4,5,6\n7,8,9'; - let parsedData = Auto(data); + let parsedData = Auto(data, schema); let expected = [['a', 'b', 'c'], [['1', '4', '7'], ['2', '5', '8'], ['3', '6', '9']]]; expect(parsedData).to.deep.equal(expected); data = '1,2,3\n4,5,6\n7,8,9'; - parsedData = Auto(data, { firstRowHeader: false }); + parsedData = Auto(data, [], { firstRowHeader: false }); expected = [[], [['1', '4', '7'], ['2', '5', '8'], ['3', '6', '9']]]; expect(parsedData).to.deep.equal(expected); }); it('should throw error on invalid data', () => { let data; - const mockFn = () => { Auto(data); }; + const mockFn = () => { Auto(data, schema); }; const errMSG = 'Couldn\'t detect the data format'; data = 2; diff --git a/src/converter/dsv-arr.js b/src/converter/dsv-arr.js index 845dc13..e8a55b5 100644 --- a/src/converter/dsv-arr.js +++ b/src/converter/dsv-arr.js @@ -17,27 +17,28 @@ import { columnMajor } from '../utils'; * [7, 8, 9] * ]; */ -function DSVArr (arr, options) { +function DSVArr (arr, schema, options) { + if (!Array.isArray(schema)) { + throw new Error('Schema missing or is in an unsupported format'); + } const defaultOption = { firstRowHeader: true, }; + const schemaFields = schema.map(unitSchema => unitSchema.name); options = Object.assign({}, defaultOption, options); - let header; const columns = []; const push = columnMajor(columns); if (options.firstRowHeader) { - // If header present then mutate the array. + // If header present then remove the first header row. // Do in-place mutation to save space. - header = arr.splice(0, 1)[0]; - } else { - header = []; + arr.splice(0, 1)[0]; } arr.forEach(field => push(...field)); - return [header, columns]; + return [schemaFields, columns]; } export default DSVArr; diff --git a/src/converter/dsv-arr.spec.js b/src/converter/dsv-arr.spec.js index e165407..734f6fc 100644 --- a/src/converter/dsv-arr.spec.js +++ b/src/converter/dsv-arr.spec.js @@ -1,10 +1,30 @@ -/* global describe, it */ +/* global describe, it, beforeEach */ /* eslint-disable no-unused-expressions */ import { expect } from 'chai'; import DSVArr from './dsv-arr'; describe('DSVArr Converter', () => { + let schema; + beforeEach(() => { + schema = [ + { + name: 'a', + type: 'measure', + subtype: 'continuous' + }, + { + name: 'b', + type: 'measure', + subtype: 'continuous' + }, + { + name: 'c', + type: 'measure', + subtype: 'continuous' + } + ]; + }); describe('#DSVArr', () => { it('should parse the DSV array data with header names', () => { const data = [ @@ -17,7 +37,7 @@ describe('DSVArr Converter', () => { firstRowHeader: true }; - const parsedData = DSVArr(data, option); + const parsedData = DSVArr(data, schema, option); const expected = [['a', 'b', 'c'], [[1, 4, 7], [2, 5, 8], [3, 6, 9]]]; expect(parsedData).to.deep.equal(expected); @@ -33,7 +53,7 @@ describe('DSVArr Converter', () => { firstRowHeader: false }; - const parsedData = DSVArr(data, option); + const parsedData = DSVArr(data, [], option); const expected = [[], [[1, 4, 7], [2, 5, 8], [3, 6, 9]]]; expect(parsedData).to.deep.equal(expected); @@ -47,7 +67,7 @@ describe('DSVArr Converter', () => { [4, 5, 6], [7, 8, 9] ]; - let parsedData = DSVArr(data); + let parsedData = DSVArr(data, schema); let expected = [['a', 'b', 'c'], [[1, 4, 7], [2, 5, 8], [3, 6, 9]]]; expect(parsedData).to.deep.equal(expected); @@ -57,9 +77,21 @@ describe('DSVArr Converter', () => { [4, 5, 6], [7, 8, 9] ]; - parsedData = DSVArr(data); - expected = [[1, 2, 3], [[4, 7], [5, 8], [6, 9]]]; + parsedData = DSVArr(data, schema); + expected = [['a', 'b', 'c'], [[4, 7], [5, 8], [6, 9]]]; expect(parsedData).to.deep.equal(expected); }); + + it('should throw error if schema is not an array', () => { + const data = [ + ['a', 'b', 'c'], + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], + ]; + const mockedparsedDataFn = () => DSVArr(data, 'schema'); + + expect(mockedparsedDataFn).to.throw('Schema missing or is in an unsupported format'); + }); }); }); diff --git a/src/converter/dsv-str.js b/src/converter/dsv-str.js index 001241b..0b4a859 100644 --- a/src/converter/dsv-str.js +++ b/src/converter/dsv-str.js @@ -22,7 +22,7 @@ import DSVArr from './dsv-arr'; * 7,8,9 * ` */ -function DSVStr (str, options) { +function DSVStr (str, schema, options) { const defaultOption = { firstRowHeader: true, fieldSeparator: ',' @@ -30,7 +30,7 @@ function DSVStr (str, options) { options = Object.assign({}, defaultOption, options); const dsv = d3Dsv(options.fieldSeparator); - return DSVArr(dsv.parseRows(str), options); + return DSVArr(dsv.parseRows(str), schema, options); } export default DSVStr; diff --git a/src/converter/dsv-str.spec.js b/src/converter/dsv-str.spec.js index e2c5985..47e4ab4 100644 --- a/src/converter/dsv-str.spec.js +++ b/src/converter/dsv-str.spec.js @@ -1,10 +1,30 @@ -/* global describe, it */ +/* global describe, it, beforeEach */ /* eslint-disable no-unused-expressions */ import { expect } from 'chai'; import DSVStr from './dsv-str'; describe('DSVStr Converter', () => { + let schema; + beforeEach(() => { + schema = [ + { + name: 'a', + type: 'measure', + subtype: 'continuous' + }, + { + name: 'b', + type: 'measure', + subtype: 'continuous' + }, + { + name: 'c', + type: 'measure', + subtype: 'continuous' + } + ]; + }); describe('#DSVStr', () => { it('should parse the DSV string data with header names', () => { const data = 'a,b,c\n1,2,3\n4,5,6\n7,8,9'; @@ -13,7 +33,7 @@ describe('DSVStr Converter', () => { fieldSeparator: ',' }; - const parsedData = DSVStr(data, option); + const parsedData = DSVStr(data, schema, option); const expected = [['a', 'b', 'c'], [['1', '4', '7'], ['2', '5', '8'], ['3', '6', '9']]]; expect(parsedData).to.deep.equal(expected); @@ -26,7 +46,7 @@ describe('DSVStr Converter', () => { fieldSeparator: ',' }; - const parsedData = DSVStr(data, option); + const parsedData = DSVStr(data, [], option); const expected = [[], [['1', '4', '7'], ['2', '5', '8'], ['3', '6', '9']]]; expect(parsedData).to.deep.equal(expected); @@ -39,7 +59,7 @@ describe('DSVStr Converter', () => { fieldSeparator: '|' }; - const parsedData = DSVStr(data, option); + const parsedData = DSVStr(data, schema, option); const expected = [['a', 'b', 'c'], [['1', '4', '7'], ['2', '5', '8'], ['3', '6', '9']]]; expect(parsedData).to.deep.equal(expected); @@ -48,15 +68,15 @@ describe('DSVStr Converter', () => { it('should parse the DSV string data with default options', () => { // With header names let data = 'a,b,c\n1,2,3\n4,5,6\n7,8,9'; - let parsedData = DSVStr(data); + let parsedData = DSVStr(data, schema); let expected = [['a', 'b', 'c'], [['1', '4', '7'], ['2', '5', '8'], ['3', '6', '9']]]; expect(parsedData).to.deep.equal(expected); // Without header names data = '1,2,3\n4,5,6\n7,8,9'; - parsedData = DSVStr(data); - expected = [['1', '2', '3'], [['4', '7'], ['5', '8'], ['6', '9']]]; - expect(parsedData).to.deep.equal(expected); + const mockedFn = () => DSVStr(data); + + expect(mockedFn).to.throw('Schema missing or is in an unsupported format'); }); }); }); diff --git a/src/converter/flat-json.js b/src/converter/flat-json.js index f020009..14f0bc8 100644 --- a/src/converter/flat-json.js +++ b/src/converter/flat-json.js @@ -26,24 +26,29 @@ import { columnMajor } from '../utils'; * } * ]; */ -function FlatJSON (arr) { +function FlatJSON (arr, schema) { + if (!Array.isArray(schema)) { + throw new Error('Schema missing or is in an unsupported format'); + } + const header = {}; let i = 0; let insertionIndex; const columns = []; const push = columnMajor(columns); + const schemaFieldsName = schema.map(unitSchema => unitSchema.name); arr.forEach((item) => { const fields = []; - for (let key in item) { - if (key in header) { - insertionIndex = header[key]; + schemaFieldsName.forEach((unitSchema) => { + if (unitSchema in header) { + insertionIndex = header[unitSchema]; } else { - header[key] = i++; + header[unitSchema] = i++; insertionIndex = i - 1; } - fields[insertionIndex] = item[key]; - } + fields[insertionIndex] = item[unitSchema]; + }); push(...fields); }); diff --git a/src/converter/flat-json.spec.js b/src/converter/flat-json.spec.js index fc451b4..543e0c9 100644 --- a/src/converter/flat-json.spec.js +++ b/src/converter/flat-json.spec.js @@ -1,43 +1,80 @@ -/* global describe, it */ +/* global describe, it, beforeEach */ /* eslint-disable no-unused-expressions */ import { expect } from 'chai'; import FlatJSON from './flat-json'; describe('FlatJSON Converter', () => { + let data; + beforeEach(() => { + data = [ + { + a: 1, + b: 2, + c: 3 + }, + { + a: 4, + b: 5, + c: 6 + }, + { + a: 7, + b: 8, + c: 9 + } + ]; + }); + describe('#FlatJSON', () => { it('should parse the JSON data', () => { - const data = [ + const schema = [ { - a: 1, - b: 2, - c: 3 + name: 'a', + type: 'measure', + subtype: 'continuous' }, { - a: 4, - b: 5, - c: 6 + name: 'b', + type: 'measure', + subtype: 'continuous' }, { - a: 7, - b: 8, - c: 9 + name: 'c', + type: 'measure', + subtype: 'continuous' } ]; - const parsedData = FlatJSON(data); + const parsedData = FlatJSON(data, schema); const expected = [['a', 'b', 'c'], [[1, 4, 7], [2, 5, 8], [3, 6, 9]]]; expect(parsedData).to.deep.equal(expected); }); it('should handle the empty JSON data', () => { - const data = []; + data = []; + const schema = []; - const parsedData = FlatJSON(data); + const parsedData = FlatJSON(data, schema); const expected = [[], []]; expect(parsedData).to.deep.equal(expected); }); + + it('should handle return empty JSON data when supplied schema is an empty array', () => { + const schema = []; + + const parsedData = FlatJSON(data, schema); + const expected = [[], []]; + + expect(parsedData).to.deep.equal(expected); + }); + + it('should throw error if schema is not an array', () => { + const mockedparsedDataFn = () => FlatJSON(data, 'schema'); + + expect(mockedparsedDataFn).to.throw('Schema missing or is in an unsupported format'); + }); }); }); diff --git a/src/datamodel.js b/src/datamodel.js index 307b860..31e986e 100644 --- a/src/datamodel.js +++ b/src/datamodel.js @@ -431,11 +431,13 @@ class DataModel extends Relation { this._colIdentifier += `,${fieldName}`; const partialFieldspace = this._partialFieldspace; const cachedValueObjects = partialFieldspace._cachedValueObjects; + const formattedData = field.formattedData(); + const rawData = field.partialField.data; if (!partialFieldspace.fieldsObj()[field.name()]) { partialFieldspace.fields.push(field); cachedValueObjects.forEach((obj, i) => { - obj[field.name()] = new Value(field.partialField.data[i], field); + obj[field.name()] = new Value(formattedData[i], rawData[i], field); }); } else { const fieldIndex = partialFieldspace.fields.findIndex(fieldinst => fieldinst.name() === fieldName); diff --git a/src/fields/temporal/index.js b/src/fields/temporal/index.js index d190f33..0b3c540 100644 --- a/src/fields/temporal/index.js +++ b/src/fields/temporal/index.js @@ -98,20 +98,25 @@ export default class Temporal extends Dimension { } /** - * Returns the formatted version of the underlying field data. - * + * Returns the formatted version of the underlying field data + * If data is of type invalid or has missing format use the raw value * @public * @override * @return {Array} Returns the formatted data. */ formattedData () { const data = []; + const dataFormat = this.format(); + rowDiffsetIterator(this.rowDiffset, (i) => { const datum = this.partialField.data[i]; - if (datum instanceof InvalidAwareTypes) { - data.push(datum); + // If value is of invalid type or format is missing + if (InvalidAwareTypes.isInvalid(datum) || (!dataFormat && Number.isFinite(datum))) { + // Use the invalid map value or the raw value + const parsedDatum = InvalidAwareTypes.getInvalidType(datum) || datum; + data.push(parsedDatum); } else { - data.push(DateTimeFormatter.formatAs(datum, this.format())); + data.push(DateTimeFormatter.formatAs(datum, dataFormat)); } }); return data; diff --git a/src/fields/temporal/index.spec.js b/src/fields/temporal/index.spec.js index 45de69a..86afd4d 100644 --- a/src/fields/temporal/index.spec.js +++ b/src/fields/temporal/index.spec.js @@ -111,13 +111,48 @@ describe('Temporal', () => { }); describe('#formattedData', () => { + const data1 = [ + '2017-03-01', + undefined, + '2017-03-02', + '2017-03-03', + '2018-01-06', + null, + '2019-11-07', + '2017-03-02' + ]; + it('should return the formatted data', () => { - const data1 = ['2017-03-01', '2017-03-02', '2017-03-03', '2018-01-06', '2019-11-07', null, '2017-03-02']; temParser = new TemporalParser(schema); partField = new PartialField(schema.name, data1, schema, temParser); rowDiffset = '1-2,4-5'; tempField = new Temporal(partField, rowDiffset); - const expected = ['2017-03-02', '2017-03-03', '2019-11-07', DataModel.InvalidAwareTypes.NULL]; + const expected = [ + DataModel.InvalidAwareTypes.NA, + '2017-03-02', + '2018-01-06', + DataModel.InvalidAwareTypes.NULL + ]; + expect(tempField.formattedData()).to.eql(expected); + }); + + it('should use the raw date value if format is missing in schema', () => { + const schemaWithoutType = { + name: 'Date', + type: 'dimension', + subtype: DimensionSubtype.TEMPORAL + }; + temParser = new TemporalParser(schemaWithoutType); + partField = new PartialField(schema.name, data1, schemaWithoutType, temParser); + rowDiffset = '1-2,5-7'; + tempField = new Temporal(partField, rowDiffset); + const expected = [ + DataModel.InvalidAwareTypes.NA, + 1488412800000, + DataModel.InvalidAwareTypes.NULL, + 1573084800000, + 1488412800000, + ]; expect(tempField.formattedData()).to.eql(expected); }); }); diff --git a/src/helper.js b/src/helper.js index e2ea7a3..2da2f26 100644 --- a/src/helper.js +++ b/src/helper.js @@ -13,17 +13,21 @@ import { extend2, detectDataFormat } from './utils'; /** * Prepares the selection data. */ -function prepareSelectionData (fields, i) { +function prepareSelectionData (fields, formattedData, rawData, i) { const resp = {}; - for (let field of fields) { - resp[field.name()] = new Value(field.partialField.data[i], field); + + for (const [key, field] of fields.entries()) { + resp[field.name()] = new Value(formattedData[key][i], rawData[key][i], field); } return resp; } export function prepareJoinData (fields) { const resp = {}; - Object.keys(fields).forEach((key) => { resp[key] = new Value(fields[key], key); }); + + for (const key in fields) { + resp[key] = new Value(fields[key].formattedValue, fields[key].rawValue, key); + } return resp; } @@ -141,8 +145,11 @@ export const selectHelper = (clonedDm, selectFn, config, sourceDm, iterator) => const { mode } = config; const rowDiffset = clonedDm._rowDiffset; const fields = clonedDm.getPartialFieldspace().fields; + const formattedFieldsData = fields.map(field => field.formattedData()); + const rawFieldsData = fields.map(field => field.data()); + const selectorHelperFn = index => selectFn( - prepareSelectionData(fields, index), + prepareSelectionData(fields, formattedFieldsData, rawFieldsData, index), index, cloneProvider, cachedStore @@ -211,13 +218,13 @@ export const filterPropagationModel = (model, propModels, config = {}) => { }); } - keyFn = (arr, fields, idx) => fields[arr[idx]].value; + keyFn = (arr, fields, idx) => fields[arr[idx]].internalValue; return data.length ? (fields) => { const present = dLen ? valuesMap[getKey(dimensions, fields, keyFn)] : true; if (filterByMeasure) { - return measures.every(field => fields[field].value >= domain[field][0] && - fields[field].value <= domain[field][1]) && present; + return measures.every(field => fields[field].internalValue >= domain[field][0] && + fields[field].internalValue <= domain[field][1]) && present; } return present; } : () => false; @@ -264,7 +271,7 @@ export const splitWithSelect = (sourceDm, dimensionArr, reducerFn = val => val, cloned._rowDiffset = splitRowDiffset[e].join(','); cloned.__calculateFieldspace().calculateFieldsConfig(); - const derivationFormula = fields => dimensionArr.every(_ => fields[_].value === derivation.keys[_]); + const derivationFormula = fields => dimensionArr.every(_ => fields[_].internalValue === derivation.keys[_]); // Store reference to child model and selector function if (saveChild) { persistDerivations(sourceDm, cloned, DM_DERIVATIVES.SELECT, config, derivationFormula); @@ -419,7 +426,7 @@ export const updateData = (relation, data, schema, options) => { throw new Error(`No converter function found for ${options.dataFormat} format`); } - const [header, formattedData] = converterFn(data, options); + const [header, formattedData] = converterFn(data, schema, options); resolveFieldName(schema, header); const fieldArr = createFields(formattedData, schema, header); @@ -432,8 +439,11 @@ export const updateData = (relation, data, schema, options) => { // This stores the value objects which is passed to the filter method when selection operation is done. const valueObjects = []; + const { fields } = nameSpace; + const rawFieldsData = fields.map(field => field.data()); + const formattedFieldsData = fields.map(field => field.formattedData()); rowDiffsetIterator(relation._rowDiffset, (i) => { - valueObjects[i] = prepareSelectionData(nameSpace.fields, i); + valueObjects[i] = prepareSelectionData(fields, formattedFieldsData, rawFieldsData, i); }); nameSpace._cachedValueObjects = valueObjects; @@ -448,15 +458,15 @@ export const fieldInSchema = (schema, field) => { for (; i < schema.length; ++i) { if (field === schema[i].name) { return { + name: field, type: schema[i].subtype || schema[i].type, - index: i + index: i, }; } } return null; }; - export const getDerivationArguments = (derivation) => { let params = []; let operation; @@ -468,6 +478,9 @@ export const getDerivationArguments = (derivation) => { case DM_DERIVATIVES.PROJECT: params = [derivation.meta.actualProjField]; break; + case DM_DERIVATIVES.SORT: + params = [derivation.criteria]; + break; case DM_DERIVATIVES.GROUPBY: operation = 'groupBy'; params = [derivation.meta.groupByString.split(','), derivation.criteria]; @@ -692,3 +705,17 @@ export const getNormalizedProFields = (projField, allFields, fieldConfig) => { }, []); return Array.from(new Set(normalizedProjField)).map(field => field.trim()); }; + +/** + * Get the numberFormatted value if numberFormat present, + * else returns the supplied value. + * @param {Object} field Field Instance + * @param {Number|String} value + * @return {Number|String} + */ +export const getNumberFormattedVal = (field, value) => { + if (field.numberFormat) { + return field.numberFormat()(value); + } + return value; +}; diff --git a/src/index.spec.js b/src/index.spec.js index 64e5024..127ab33 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -980,6 +980,163 @@ describe('DataModel', () => { expect(sortedDm.getData()).to.deep.equal(expData); }); + it('should retain the order when null is provided for a field', () => { + const data = [ + { age: 30, job: 'management', marital: 'married' }, + { age: 59, job: 'blue-collar', marital: 'married' }, + { age: 35, job: 'management', marital: 'single' }, + { age: 57, job: 'self-employed', marital: 'married' }, + { age: 28, job: 'blue-collar', marital: 'married' }, + { age: 30, job: 'blue-collar', marital: 'single' }, + ]; + const schema = [ + { name: 'age', type: 'measure' }, + { name: 'job', type: 'dimension' }, + { name: 'marital', type: 'dimension' } + ]; + const dataModel = new DataModel(data, schema); + + const sortedDm = dataModel.sort([ + ['job', null], + ]); + const expData = { + data: [ + [30, 'management', 'married'], + [59, 'blue-collar', 'married'], + [35, 'management', 'single'], + [57, 'self-employed', 'married'], + [28, 'blue-collar', 'married'], + [30, 'blue-collar', 'single'], + ], + schema: [ + { name: 'age', type: 'measure', subtype: 'continuous' }, + { name: 'job', type: 'dimension', subtype: 'categorical' }, + { name: 'marital', type: 'dimension', subtype: 'categorical' } + ], + uids: [0, 1, 2, 3, 4, 5] + }; + expect(sortedDm.getData()).to.deep.equal(expData); + }); + + it('should perform multi sort without sorting first field', () => { + const data = [ + { age: 30, job: 'management', marital: 'married' }, + { age: 59, job: 'blue-collar', marital: 'married' }, + { age: 35, job: 'management', marital: 'single' }, + { age: 57, job: 'self-employed', marital: 'married' }, + { age: 28, job: 'blue-collar', marital: 'married' }, + { age: 30, job: 'blue-collar', marital: 'single' }, + ]; + const schema = [ + { name: 'age', type: 'measure' }, + { name: 'job', type: 'dimension' }, + { name: 'marital', type: 'dimension' } + ]; + const dataModel = new DataModel(data, schema); + + const sortedDm = dataModel.sort([ + ['job', null], + ['age', 'desc'], + ]); + const expData = { + data: [ + [35, 'management', 'single'], + [59, 'blue-collar', 'married'], + [30, 'management', 'married'], + [57, 'self-employed', 'married'], + [30, 'blue-collar', 'single'], + [28, 'blue-collar', 'married'] + ], + schema: [ + { name: 'age', type: 'measure', subtype: 'continuous' }, + { name: 'job', type: 'dimension', subtype: 'categorical' }, + { name: 'marital', type: 'dimension', subtype: 'categorical' } + ], + uids: [0, 1, 2, 3, 4, 5] + }; + expect(sortedDm.getData()).to.deep.equal(expData); + }); + + it('should perform multi sort without sorting second field', () => { + const data = [ + { age: 30, job: 'management', marital: 'married' }, + { age: 59, job: 'blue-collar', marital: 'married' }, + { age: 35, job: 'management', marital: 'single' }, + { age: 57, job: 'self-employed', marital: 'married' }, + { age: 28, job: 'blue-collar', marital: 'married' }, + { age: 30, job: 'blue-collar', marital: 'single' }, + ]; + const schema = [ + { name: 'age', type: 'measure' }, + { name: 'job', type: 'dimension' }, + { name: 'marital', type: 'dimension' } + ]; + const dataModel = new DataModel(data, schema); + + const sortedDm = dataModel.sort([ + ['job', 'asc'], + ['marital', null], + ['age', 'asc'], + ]); + const expData = { + data: [ + [28, 'blue-collar', 'married'], + [59, 'blue-collar', 'married'], + [30, 'blue-collar', 'single'], + [30, 'management', 'married'], + [35, 'management', 'single'], + [57, 'self-employed', 'married'] + ], + schema: [ + { name: 'age', type: 'measure', subtype: 'continuous' }, + { name: 'job', type: 'dimension', subtype: 'categorical' }, + { name: 'marital', type: 'dimension', subtype: 'categorical' } + ], + uids: [0, 1, 2, 3, 4, 5] + }; + expect(sortedDm.getData()).to.deep.equal(expData); + }); + + it('should perform multi sort while having multiple null sorted fields', () => { + const data = [ + { age: 30, job: 'management', marital: 'married' }, + { age: 59, job: 'blue-collar', marital: 'married' }, + { age: 35, job: 'management', marital: 'single' }, + { age: 57, job: 'self-employed', marital: 'married' }, + { age: 28, job: 'blue-collar', marital: 'married' }, + { age: 30, job: 'blue-collar', marital: 'single' }, + ]; + const schema = [ + { name: 'age', type: 'measure' }, + { name: 'job', type: 'dimension' }, + { name: 'marital', type: 'dimension' } + ]; + const dataModel = new DataModel(data, schema); + + const sortedDm = dataModel.sort([ + ['job', null], + ['marital', null], + ['age', 'desc'], + ]); + const expData = { + data: [ + [30, 'management', 'married'], + [59, 'blue-collar', 'married'], + [35, 'management', 'single'], + [57, 'self-employed', 'married'], + [28, 'blue-collar', 'married'], + [30, 'blue-collar', 'single'] + ], + schema: [ + { name: 'age', type: 'measure', subtype: 'continuous' }, + { name: 'job', type: 'dimension', subtype: 'categorical' }, + { name: 'marital', type: 'dimension', subtype: 'categorical' } + ], + uids: [0, 1, 2, 3, 4, 5] + }; + expect(sortedDm.getData()).to.deep.equal(expData); + }); + it('should perform sort with string data', () => { const data = [ { Name: 'Shubham', Age: '22', Gender: 'Male', Location: 'Kolkata' }, diff --git a/src/operator/cross-product.js b/src/operator/cross-product.js index 0739dad..26b69d1 100644 --- a/src/operator/cross-product.js +++ b/src/operator/cross-product.js @@ -66,13 +66,19 @@ export function crossProduct (dm1, dm2, filterFn, replaceCommonSchema = false, j userArg[dm2FieldStoreName] = {}; dm1FieldStore.fields.forEach((field) => { tuple.push(field.partialField.data[i]); - userArg[dm1FieldStoreName][field.name()] = field.partialField.data[i]; + userArg[dm1FieldStoreName][field.name()] = { + rawValue: field.partialField.data[i], + formattedValue: field.formattedData()[i], + }; }); dm2FieldStore.fields.forEach((field) => { if (!(commonSchemaList.indexOf(field.schema().name) !== -1 && replaceCommonSchema)) { tuple.push(field.partialField.data[ii]); } - userArg[dm2FieldStoreName][field.name()] = field.partialField.data[ii]; + userArg[dm2FieldStoreName][field.name()] = { + rawValue: field.partialField.data[ii], + formattedValue: field.formattedData()[ii], + }; }); let cachedStore = {}; diff --git a/src/operator/data-builder.js b/src/operator/data-builder.js index ea97943..4e4b84d 100644 --- a/src/operator/data-builder.js +++ b/src/operator/data-builder.js @@ -1,149 +1,5 @@ -import { DimensionSubtype, MeasureSubtype } from '../enums'; import { rowDiffsetIterator } from './row-diffset-iterator'; -import { mergeSort } from './merge-sort'; -import { fieldInSchema } from '../helper'; -import { isCallable, isArray, } from '../utils'; -/** - * Generates the sorting functions to sort the data of a DataModel instance - * according to the input data type. - * - * @param {string} dataType - The data type e.g. 'measure', 'datetime' etc. - * @param {string} sortType - The sorting order i.e. 'asc' or 'desc'. - * @param {integer} index - The index of the data which will be sorted. - * @return {Function} Returns the the sorting function. - */ -function getSortFn (dataType, sortType, index) { - let retFunc; - switch (dataType) { - case MeasureSubtype.CONTINUOUS: - case DimensionSubtype.TEMPORAL: - if (sortType === 'desc') { - retFunc = (a, b) => b[index] - a[index]; - } else { - retFunc = (a, b) => a[index] - b[index]; - } - break; - default: - retFunc = (a, b) => { - const a1 = `${a[index]}`; - const b1 = `${b[index]}`; - if (a1 < b1) { - return sortType === 'desc' ? 1 : -1; - } - if (a1 > b1) { - return sortType === 'desc' ? -1 : 1; - } - return 0; - }; - } - return retFunc; -} - -/** - * Groups the data according to the specified target field. - * - * @param {Array} data - The input data array. - * @param {number} fieldIndex - The target field index within schema array. - * @return {Array} Returns an array containing the grouped data. - */ -function groupData(data, fieldIndex) { - const hashMap = new Map(); - const groupedData = []; - - data.forEach((datum) => { - const fieldVal = datum[fieldIndex]; - if (hashMap.has(fieldVal)) { - groupedData[hashMap.get(fieldVal)][1].push(datum); - } else { - groupedData.push([fieldVal, [datum]]); - hashMap.set(fieldVal, groupedData.length - 1); - } - }); - - return groupedData; -} - -/** - * Creates the argument value used for sorting function when sort is done - * with another fields. - * - * @param {Array} groupedDatum - The grouped datum for a single dimension field value. - * @param {Array} targetFields - An array of the sorting fields. - * @param {Array} targetFieldDetails - An array of the sorting field details in schema. - * @return {Object} Returns an object containing the value of sorting fields and the target field name. - */ -function createSortingFnArg(groupedDatum, targetFields, targetFieldDetails) { - const arg = { - label: groupedDatum[0] - }; - - targetFields.reduce((acc, next, idx) => { - acc[next] = groupedDatum[1].map(datum => datum[targetFieldDetails[idx].index]); - return acc; - }, arg); - - return arg; -} - -/** - * Sorts the data before return in dataBuilder. - * - * @param {Object} dataObj - An object containing the data and schema. - * @param {Array} sortingDetails - An array containing the sorting configs. - */ -function sortData(dataObj, sortingDetails) { - const { data, schema } = dataObj; - let fieldName; - let sortMeta; - let fDetails; - let i = sortingDetails.length - 1; - - for (; i >= 0; i--) { - fieldName = sortingDetails[i][0]; - sortMeta = sortingDetails[i][1]; - fDetails = fieldInSchema(schema, fieldName); - - if (!fDetails) { - // eslint-disable-next-line no-continue - continue; - } - - if (isCallable(sortMeta)) { - // eslint-disable-next-line no-loop-func - mergeSort(data, (a, b) => sortMeta(a[fDetails.index], b[fDetails.index])); - } else if (isArray(sortMeta)) { - const groupedData = groupData(data, fDetails.index); - const sortingFn = sortMeta[sortMeta.length - 1]; - const targetFields = sortMeta.slice(0, sortMeta.length - 1); - const targetFieldDetails = targetFields.map(f => fieldInSchema(schema, f)); - - groupedData.forEach((groupedDatum) => { - groupedDatum.push(createSortingFnArg(groupedDatum, targetFields, targetFieldDetails)); - }); - - mergeSort(groupedData, (a, b) => { - const m = a[2]; - const n = b[2]; - return sortingFn(m, n); - }); - - // Empty the array - data.length = 0; - groupedData.forEach((datum) => { - data.push(...datum[1]); - }); - } else { - sortMeta = String(sortMeta).toLowerCase() === 'desc' ? 'desc' : 'asc'; - mergeSort(data, getSortFn(fDetails.type, sortMeta, fDetails.index)); - } - } - - dataObj.uids = []; - data.forEach((value) => { - dataObj.uids.push(value.pop()); - }); -} - +import { sortData } from './sort'; /** * Builds the actual data array. diff --git a/src/operator/natural-join-filter-function.js b/src/operator/natural-join-filter-function.js index 9cdbf7b..47ecaa5 100644 --- a/src/operator/natural-join-filter-function.js +++ b/src/operator/natural-join-filter-function.js @@ -19,8 +19,8 @@ export function naturalJoinFilter (dm1, dm2) { return (dm1Fields, dm2Fields) => { let retainTuple = true; commonSchemaArr.forEach((fieldName) => { - if (dm1Fields[fieldName].value === - dm2Fields[fieldName].value && retainTuple) { + if (dm1Fields[fieldName].internalValue === + dm2Fields[fieldName].internalValue && retainTuple) { retainTuple = true; } else { retainTuple = false; diff --git a/src/operator/sort.js b/src/operator/sort.js new file mode 100644 index 0000000..1015a8a --- /dev/null +++ b/src/operator/sort.js @@ -0,0 +1,257 @@ +import { DimensionSubtype, MeasureSubtype } from '../enums'; +import { mergeSort } from './merge-sort'; +import { fieldInSchema } from '../helper'; +import { isCallable, isArray } from '../utils'; + +/** + * Generates the sorting functions to sort the data of a DataModel instance + * according to the input data type. + * + * @param {string} dataType - The data type e.g. 'measure', 'datetime' etc. + * @param {string} sortType - The sorting order i.e. 'asc' or 'desc'. + * @return {Function} Returns the the sorting function. + */ +function getSortFn (dataType, sortType) { + let retFunc; + + switch (dataType) { + case MeasureSubtype.CONTINUOUS: + case DimensionSubtype.TEMPORAL: + if (sortType === 'asc') { + retFunc = (a, b) => a - b; + } else { + retFunc = (a, b) => b - a; + } + break; + default: + if (sortType === 'asc') { + retFunc = (a, b) => { + a = `${a}`; + b = `${b}`; + if (a === b) { + return 0; + } + return a > b ? 1 : -1; + }; + } else { + retFunc = (a, b) => { + a = `${a}`; + b = `${b}`; + if (a === b) { + return 0; + } + return a > b ? -1 : 1; + }; + } + } + + return retFunc; +} + +/** + * Resolves the actual sorting function based on sorting string value. + * + * @param {Object} fDetails - The target field info. + * @param {string} strSortOrder - The sort order value. + * @return {Function} Returns the sorting function. + */ +function resolveStrSortOrder (fDetails, strSortOrder) { + const sortOrder = String(strSortOrder).toLowerCase() === 'desc' ? 'desc' : 'asc'; + return getSortFn(fDetails.type, sortOrder); +} + +/** + * Groups the data according to the specified target field. + * + * @param {Array} data - The input data array. + * @param {number} fieldIndex - The target field index within schema array. + * @return {Array} Returns an array containing the grouped data. + */ +function groupData (data, fieldIndex) { + const hashMap = new Map(); + const groupedData = []; + + data.forEach((datum) => { + const fieldVal = datum[fieldIndex]; + if (hashMap.has(fieldVal)) { + groupedData[hashMap.get(fieldVal)][1].push(datum); + } else { + groupedData.push([fieldVal, [datum]]); + hashMap.set(fieldVal, groupedData.length - 1); + } + }); + + return groupedData; +} + +/** + * Creates the argument value used for sorting function when sort is done + * with another fields. + * + * @param {Array} groupedDatum - The grouped datum for a single dimension field value. + * @param {Array} targetFields - An array of the sorting fields. + * @param {Array} targetFieldDetails - An array of the sorting field details in schema. + * @return {Object} Returns an object containing the value of sorting fields and the target field name. + */ +function createSortingFnArg (groupedDatum, targetFields, targetFieldDetails) { + const arg = { + label: groupedDatum[0] + }; + + targetFields.reduce((acc, next, idx) => { + acc[next] = groupedDatum[1].map(datum => datum[targetFieldDetails[idx].index]); + return acc; + }, arg); + + return arg; +} + +/** + * Sorts the data by applying the standard sorting mechanism. + * + * @param {Array} data - The input data array. + * @param {Array} schema - The data schema. + * @param {Array} sortingDetails - An array containing the sorting configs. + */ +function applyStandardSort (data, schema, sortingDetails) { + let fieldName; + let sortMeta; + let fDetails; + let i = sortingDetails.length - 1; + + for (; i >= 0; i--) { + fieldName = sortingDetails[i][0]; + sortMeta = sortingDetails[i][1]; + fDetails = fieldInSchema(schema, fieldName); + + if (!fDetails) { + // eslint-disable-next-line no-continue + continue; + } + + if (isCallable(sortMeta)) { + // eslint-disable-next-line no-loop-func + mergeSort(data, (a, b) => sortMeta(a[fDetails.index], b[fDetails.index])); + } else if (isArray(sortMeta)) { + const groupedData = groupData(data, fDetails.index); + const sortingFn = sortMeta[sortMeta.length - 1]; + const targetFields = sortMeta.slice(0, sortMeta.length - 1); + const targetFieldDetails = targetFields.map(f => fieldInSchema(schema, f)); + + groupedData.forEach((groupedDatum) => { + groupedDatum.push(createSortingFnArg(groupedDatum, targetFields, targetFieldDetails)); + }); + + mergeSort(groupedData, (a, b) => { + const m = a[2]; + const n = b[2]; + return sortingFn(m, n); + }); + + // Empty the array + data.length = 0; + groupedData.forEach((datum) => { + data.push(...datum[1]); + }); + } else { + const sortFn = resolveStrSortOrder(fDetails, sortMeta); + // eslint-disable-next-line no-loop-func + mergeSort(data, (a, b) => sortFn(a[fDetails.index], b[fDetails.index])); + } + } +} + +/** + * Creates a map based on grouping. + * + * @param {Array} depColumns - The dependency columns' info. + * @param {Array} data - The input data. + * @param {Array} schema - The data schema. + * @param {Array} sortingDetails - The sorting details for standard sorting. + * @return {Map} Returns a map. + */ +const makeGroupMapAndSort = (depColumns, data, schema, sortingDetails) => { + if (depColumns.length === 0) { return data; } + + const targetCol = depColumns[0]; + const map = new Map(); + + data.reduce((acc, currRow) => { + const fVal = currRow[targetCol.index]; + if (acc.has(fVal)) { + acc.get(fVal).push(currRow); + } else { + acc.set(fVal, [currRow]); + } + return acc; + }, map); + + for (let [key, val] of map) { + const nMap = makeGroupMapAndSort(depColumns.slice(1), val, schema, sortingDetails); + map.set(key, nMap); + if (Array.isArray(nMap)) { + applyStandardSort(nMap, schema, sortingDetails); + } + } + + return map; +}; + +/** + * Sorts the data by retaining the position/order of a particular field. + * + * @param {Array} data - The input data array. + * @param {Array} schema - The data schema. + * @param {Array} sortingDetails - An array containing the sorting configs. + * @param {Array} depColumns - The dependency column list. + * @return {Array} Returns the sorted data. + */ +function applyGroupSort (data, schema, sortingDetails, depColumns) { + sortingDetails = sortingDetails.filter((detail) => { + if (detail[1] === null) { + depColumns.push(detail[0]); + return false; + } + return true; + }); + if (sortingDetails.length === 0) { return data; } + + depColumns = depColumns.map(c => fieldInSchema(schema, c)); + + const sortedGroupMap = makeGroupMapAndSort(depColumns, data, schema, sortingDetails); + return data.map((row) => { + let i = 0; + let nextMap = sortedGroupMap; + + while (!Array.isArray(nextMap)) { + nextMap = nextMap.get(row[depColumns[i++].index]); + } + + return nextMap.shift(); + }); +} + +/** + * Sorts the data. + * + * @param {Object} dataObj - An object containing the data and schema. + * @param {Array} sortingDetails - An array containing the sorting configs. + */ +export function sortData (dataObj, sortingDetails) { + let { schema, data } = dataObj; + + sortingDetails = sortingDetails.filter(sDetial => !!fieldInSchema(schema, sDetial[0])); + if (sortingDetails.length === 0) { return; } + + let groupSortingIdx = sortingDetails.findIndex(sDetial => sDetial[1] === null); + groupSortingIdx = groupSortingIdx !== -1 ? groupSortingIdx : sortingDetails.length; + + const standardSortingDetails = sortingDetails.slice(0, groupSortingIdx); + const groupSortingDetails = sortingDetails.slice(groupSortingIdx); + + applyStandardSort(data, schema, standardSortingDetails); + data = applyGroupSort(data, schema, groupSortingDetails, standardSortingDetails.map(detail => detail[0])); + + dataObj.uids = data.map(row => row.pop()); + dataObj.data = data; +} diff --git a/src/value.js b/src/value.js index b91bcec..46413b7 100644 --- a/src/value.js +++ b/src/value.js @@ -1,3 +1,5 @@ +import { getNumberFormattedVal } from './helper'; + /** * The wrapper class on top of the primitive value of a field. * @@ -12,12 +14,28 @@ class Value { * @param {*} val - the primitive value from the field cell. * @param {string | Field} field - The field from which the value belongs. */ - constructor (val, field) { - Object.defineProperty(this, '_value', { - enumerable: false, - configurable: false, - writable: false, - value: val + constructor (value, rawValue, field) { + const formattedValue = getNumberFormattedVal(field, value); + + Object.defineProperties(this, { + _value: { + enumerable: false, + configurable: false, + writable: false, + value + }, + _formattedValue: { + enumerable: false, + configurable: false, + writable: false, + value: formattedValue + }, + _internalValue: { + enumerable: false, + configurable: false, + writable: false, + value: rawValue + } }); this.field = field; @@ -32,6 +50,20 @@ class Value { return this._value; } + /** + * Returns the parsed value of field + */ + get formattedValue () { + return this._formattedValue; + } + + /** + * Returns the internal value of field + */ + get internalValue () { + return this._internalValue; + } + /** * Converts to human readable string. * diff --git a/src/value.spec.js b/src/value.spec.js index 61e12ba..75c682c 100644 --- a/src/value.spec.js +++ b/src/value.spec.js @@ -7,30 +7,40 @@ import Value from './value'; describe('Value', () => { const fieldValue = 'India'; const fieldName = 'Country'; - const anotherFieldValue = 10; + const rawDate = 31516200000; + const formattedDate = '1970-01-01'; const anotherFieldName = 'Ranking'; let value; let anotherValue; beforeEach(() => { - value = new Value(fieldValue, fieldName); - anotherValue = new Value(anotherFieldValue, anotherFieldName); + value = new Value(fieldValue, fieldValue, fieldName); + anotherValue = new Value(formattedDate, rawDate, anotherFieldName); }); it('should hold primitive value of a field cell', () => { expect(value.value).to.equal(fieldValue); + expect(value.formattedValue).to.equal(fieldValue); + expect(value.internalValue).to.equal(fieldValue); expect(value.field).to.equal(fieldName); + + expect(anotherValue.value).to.equal(formattedDate); + expect(anotherValue.formattedValue).to.equal(formattedDate); + expect(anotherValue.internalValue).to.equal(rawDate); + expect(anotherValue.field).to.equal(anotherFieldName); }); describe('#toString', () => { it('should return human readable string of the field value', () => { expect(value.toString()).to.equal(String(fieldValue)); + expect(anotherValue.toString()).to.equal(String(formattedDate)); }); }); describe('#valueOf', () => { it('should return the field value', () => { - expect(anotherValue.valueOf()).to.equal(anotherFieldValue); + expect(value.valueOf()).to.equal(fieldValue); + expect(anotherValue.valueOf()).to.equal(formattedDate); }); }); });