diff --git a/gulliver/js/d3/d3.js b/gulliver/js/d3/d3.js new file mode 100644 index 000000000..88550ae51 --- /dev/null +++ b/gulliver/js/d3/d3.js @@ -0,0 +1,5 @@ +!function(){function n(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function t(n){return null!=n&&!isNaN(n)}function e(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function r(n){return n.length}function u(n){for(var t=1;n*t%1;)t*=10;return t}function i(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function o(){}function a(n){return ia+n in this}function c(n){return n=ia+n,n in this&&delete this[n]}function s(){var n=[];return this.forEach(function(t){n.push(t)}),n}function l(){var n=0;for(var t in this)t.charCodeAt(0)===oa&&++n;return n}function f(){for(var n in this)if(n.charCodeAt(0)===oa)return!1;return!0}function h(){}function g(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function p(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=aa.length;r>e;++e){var u=aa[e]+t;if(u in n)return u}}function v(){}function d(){}function m(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function U(n){return sa(n,da),n}function j(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.substring(0,a));var s=ya.get(n);return s&&(n=s,c=Y),a?t?u:r:t?v:i}function O(n,t){return function(e){var r=Zo.event;Zo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Zo.event=r}}}function Y(n,t){var e=O(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function I(){var n=".dragsuppress-"+ ++Ma,t="click"+n,e=Zo.select(Wo).on("touchmove"+n,y).on("dragstart"+n,y).on("selectstart"+n,y);if(xa){var r=Bo.style,u=r[xa];r[xa]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),xa&&(r[xa]=u),i&&(e.on(t,function(){y(),o()},!0),setTimeout(o,0))}}function Z(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>_a&&(Wo.scrollX||Wo.scrollY)){e=Zo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();_a=!(u.f||u.e),e.remove()}return _a?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function V(){return Zo.event.changedTouches[0].identifier}function X(){return Zo.event.target}function $(){return Wo}function B(n){return n>0?1:0>n?-1:0}function W(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function J(n){return n>1?0:-1>n?ba:Math.acos(n)}function G(n){return n>1?Sa:-1>n?-Sa:Math.asin(n)}function K(n){return((n=Math.exp(n))-1/n)/2}function Q(n){return((n=Math.exp(n))+1/n)/2}function nt(n){return((n=Math.exp(2*n))-1)/(n+1)}function tt(n){return(n=Math.sin(n/2))*n}function et(){}function rt(n,t,e){return this instanceof rt?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof rt?new rt(n.h,n.s,n.l):mt(""+n,yt,rt):new rt(n,t,e)}function ut(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new gt(u(n+120),u(n),u(n-120))}function it(n,t,e){return this instanceof it?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof it?new it(n.h,n.c,n.l):n instanceof at?st(n.l,n.a,n.b):st((n=xt((n=Zo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new it(n,t,e)}function ot(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new at(e,Math.cos(n*=Aa)*t,Math.sin(n)*t)}function at(n,t,e){return this instanceof at?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof at?new at(n.l,n.a,n.b):n instanceof it?ot(n.l,n.c,n.h):xt((n=gt(n)).r,n.g,n.b):new at(n,t,e)}function ct(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=lt(u)*ja,r=lt(r)*Ha,i=lt(i)*Fa,new gt(ht(3.2404542*u-1.5371385*r-.4985314*i),ht(-.969266*u+1.8760108*r+.041556*i),ht(.0556434*u-.2040259*r+1.0572252*i))}function st(n,t,e){return n>0?new it(Math.atan2(e,t)*Ca,Math.sqrt(t*t+e*e),n):new it(0/0,0/0,n)}function lt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function ft(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function ht(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function gt(n,t,e){return this instanceof gt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof gt?new gt(n.r,n.g,n.b):mt(""+n,gt,ut):new gt(n,t,e)}function pt(n){return new gt(n>>16,255&n>>8,255&n)}function vt(n){return pt(n)+""}function dt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function mt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(_t(u[0]),_t(u[1]),_t(u[2]))}return(i=Ia.get(n))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.substring(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function yt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new rt(r,u,c)}function xt(n,t,e){n=Mt(n),t=Mt(t),e=Mt(e);var r=ft((.4124564*n+.3575761*t+.1804375*e)/ja),u=ft((.2126729*n+.7151522*t+.072175*e)/Ha),i=ft((.0193339*n+.119192*t+.9503041*e)/Fa);return at(116*u-16,500*(r-u),200*(u-i))}function Mt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function _t(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function bt(n){return"function"==typeof n?n:function(){return n}}function wt(n){return n}function St(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),kt(t,e,n,r)}}function kt(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Zo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Wo.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Zo.event;Zo.event=n;try{o.progress.call(i,c)}finally{Zo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Xo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Zo.rebind(i,o,"on"),null==r?i:i.get(Et(r))}function Et(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function At(){var n=Ct(),t=Nt()-n;t>24?(isFinite(t)&&(clearTimeout($a),$a=setTimeout(At,t)),Xa=0):(Xa=1,Wa(At))}function Ct(){var n=Date.now();for(Ba=Za;Ba;)n>=Ba.t&&(Ba.f=Ba.c(n-Ba.t)),Ba=Ba.n;return n}function Nt(){for(var n,t=Za,e=1/0;t;)t.f?t=n?n.n=t.n:Za=t.n:(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:wt;return function(n){var e=Ga.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=Ka.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Zo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function Rt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Dt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new nc(e-1)),1),e}function i(n,e){return t(n=new nc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{nc=Rt;var r=new Rt;return r._=n,o(r,t,e)}finally{nc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Pt(n);return c.floor=c,c.round=Pt(r),c.ceil=Pt(u),c.offset=Pt(i),c.range=a,n}function Pt(n){return function(t,e){try{nc=Rt;var r=new Rt;return r._=t,n(r,e)._}finally{nc=Date}}}function Ut(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++aa;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in ec?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{nc=Rt;var t=new nc;return t._=n,r(t)}finally{nc=Date}}var r=t(n);return e.parse=function(n){try{nc=Rt;var t=r.parse(n);return t&&t._}finally{nc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=re;var x=Zo.map(),M=Ht(v),_=Ft(v),b=Ht(d),w=Ft(d),S=Ht(m),k=Ft(m),E=Ht(y),A=Ft(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return jt(n.getDate(),t,2)},e:function(n,t){return jt(n.getDate(),t,2)},H:function(n,t){return jt(n.getHours(),t,2)},I:function(n,t){return jt(n.getHours()%12||12,t,2)},j:function(n,t){return jt(1+Qa.dayOfYear(n),t,3)},L:function(n,t){return jt(n.getMilliseconds(),t,3)},m:function(n,t){return jt(n.getMonth()+1,t,2)},M:function(n,t){return jt(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return jt(n.getSeconds(),t,2)},U:function(n,t){return jt(Qa.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return jt(Qa.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return jt(n.getFullYear()%100,t,2)},Y:function(n,t){return jt(n.getFullYear()%1e4,t,4)},Z:te,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Wt,e:Wt,H:Gt,I:Gt,j:Jt,L:ne,m:Bt,M:Kt,p:l,S:Qt,U:Yt,w:Ot,W:It,x:c,X:s,y:Vt,Y:Zt,Z:Xt,"%":ee};return t}function jt(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Ht(n){return new RegExp("^(?:"+n.map(Zo.requote).join("|")+")","i")}function Ft(n){for(var t=new o,e=-1,r=n.length;++e68?1900:2e3)}function Bt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Wt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Jt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Gt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Kt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Qt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ne(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function te(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(ua(t)/60),u=ua(t)%60;return e+jt(r,"0",2)+jt(u,"0",2)}function ee(n,t,e){uc.lastIndex=0;var r=uc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function re(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);lc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;fc.point=function(o,a){fc.point=n,r=(t=o)*Aa,u=Math.cos(a=(e=a)*Aa/2+ba/4),i=Math.sin(a)},fc.lineEnd=function(){n(t,e)}}function le(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function fe(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function he(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function ge(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function pe(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function ve(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function de(n){return[Math.atan2(n[1],n[0]),G(n[2])]}function me(n,t){return ua(n[0]-t[0])a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new Ee(e,n,null,!0),s=new Ee(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new Ee(r,n,null,!1),s=new Ee(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),ke(i),ke(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ke(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r0){for(_||(i.polygonStart(),_=!0),i.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ce))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Zo.merge(g);var n=Le(m,p);g.length?(_||(i.polygonStart(),_=!0),Se(g,ze,n,e,i)):n&&(_||(i.polygonStart(),_=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),_&&(i.polygonEnd(),_=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ne(),M=t(x),_=!1;return y}}function Ce(n){return n.length>1}function Ne(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:v,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function ze(n,t){return((n=n.x)[0]<0?n[1]-Sa-ka:Sa-n[1])-((t=t.x)[0]<0?t[1]-Sa-ka:Sa-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;lc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+ba/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+ba/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>ba,k=p*x;if(lc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*wa:_,S^h>=e^m>=e){var E=he(le(f),le(n));ve(E);var A=he(u,E);ve(A);var C=(S^_>=0?-1:1)*G(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-ka>i||ka>i&&0>lc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?ba:-ba,c=ua(i-e);ua(c-ba)0?Sa:-Sa),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=ba&&(ua(e-u)ka?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function Re(n,t,e,r){var u;if(null==n)u=e*Sa,r.point(-ba,u),r.point(0,u),r.point(ba,u),r.point(ba,0),r.point(ba,-u),r.point(0,-u),r.point(-ba,-u),r.point(-ba,0),r.point(-ba,u);else if(ua(n[0]-t[0])>ka){var i=n[0]i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?ba:-ba),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(me(e,g)||me(p,g))&&(p[0]+=ka,p[1]+=ka,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&me(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=le(n),u=le(t),o=[1,0,0],a=he(r,u),c=fe(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=he(o,a),p=pe(o,f),v=pe(a,h);ge(p,v);var d=g,m=fe(p,d),y=fe(d,d),x=m*m-y*(fe(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=pe(d,(-m-M)/y);if(ge(_,p),_=de(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=ua(A-ba)A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(ua(_[0]-w)ba^(w<=_[0]&&_[0]<=S)){var z=pe(d,(-m+M)/y);return ge(z,p),[_,de(z)]}}}function u(t,e){var r=o?n:ba-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ua(i)>ka,c=sr(n,6*Aa);return Ae(t,e,c,o?[0,-n]:[-ba,n-ba])}function Pe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Ue(n,t,e,r){function u(r,u){return ua(r[0]-n)0?0:3:ua(r[0]-e)0?2:1:ua(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&W(s,i,n)>0&&++t:i[1]<=r&&W(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-kc,Math.min(kc,n)),t=Math.max(-kc,Math.min(kc,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ne(),C=Pe(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Zo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&Se(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function je(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function He(n){var t=0,e=ba/3,r=tr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*ba/180,e=n[1]*ba/180):[180*(t/ba),180*(e/ba)]},u}function Fe(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,G((i-(n*n+e*e)*u*u)/(2*u))]},e}function Oe(){function n(n,t){Ac+=u*n-r*t,r=n,u=t}var t,e,r,u;Tc.point=function(i,o){Tc.point=n,t=r=i,e=u=o},Tc.lineEnd=function(){n(t,e)}}function Ye(n,t){Cc>n&&(Cc=n),n>zc&&(zc=n),Nc>t&&(Nc=t),t>Lc&&(Lc=t)}function Ie(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ze(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ze(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ze(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ve(n,t){pc+=n,vc+=t,++dc}function Xe(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);mc+=o*(t+n)/2,yc+=o*(e+r)/2,xc+=o,Ve(t=n,e=r)}var t,e;Rc.point=function(r,u){Rc.point=n,Ve(t=r,e=u)}}function $e(){Rc.point=Ve}function Be(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);mc+=o*(r+n)/2,yc+=o*(u+t)/2,xc+=o,o=u*n-r*t,Mc+=o*(r+n),_c+=o*(u+t),bc+=3*o,Ve(r=n,u=t)}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,Ve(t=r=i,e=u=o)},Rc.lineEnd=function(){n(t,e)}}function We(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,wa)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:v};return a}function Je(n){function t(n){return(a?r:e)(n)}function e(t){return Qe(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=le([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=ua(ua(w)-1)i||ua((y*z+x*L)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Aa),a=16; +return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Ge(n){var t=Je(function(t,e){return n([t*Ca,e*Ca])});return function(n){return er(t(n))}}function Ke(n){this.stream=n}function Qe(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function nr(n){return tr(function(){return n})()}function tr(n){function t(n){return n=a(n[0]*Aa,n[1]*Aa),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*Ca,n[1]*Ca]}function r(){a=je(o=ir(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=Je(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Sc,_=wt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=er(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Sc):De((b=+n)*Aa),u()):b},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Ue(n[0][0],n[0][1],n[1][0],n[1][1]):wt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Aa,d=n[1]%360*Aa,r()):[v*Ca,d*Ca]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Aa,y=n[1]%360*Aa,x=n.length>2?n[2]%360*Aa:0,r()):[m*Ca,y*Ca,x*Ca]},Zo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function er(n){return Qe(n,function(t,e){n.point(t*Aa,e*Aa)})}function rr(n,t){return[n,t]}function ur(n,t){return[n>ba?n-wa:-ba>n?n+wa:n,t]}function ir(n,t,e){return n?t||e?je(ar(n),cr(t,e)):ar(n):t||e?cr(t,e):ur}function or(n){return function(t,e){return t+=n,[t>ba?t-wa:-ba>t?t+wa:t,e]}}function ar(n){var t=or(n);return t.invert=or(-n),t}function cr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),G(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),G(l*r-a*u)]},e}function sr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=lr(e,u),i=lr(e,i),(o>0?i>u:u>i)&&(u+=o*wa)):(u=n+o*wa,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=de([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function lr(n,t){var e=le(t);e[0]-=n,ve(e);var r=J(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-ka)%(2*Math.PI)}function fr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function hr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function gr(n){return n.source}function pr(n){return n.target}function vr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(tt(r-t)+u*o*tt(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Ca,Math.atan2(o,Math.sqrt(r*r+u*u))*Ca]}:function(){return[n*Ca,t*Ca]};return p.distance=h,p}function dr(){function n(n,u){var i=Math.sin(u*=Aa),o=Math.cos(u),a=ua((n*=Aa)-t),c=Math.cos(a);Dc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Pc.point=function(u,i){t=u*Aa,e=Math.sin(i*=Aa),r=Math.cos(i),Pc.point=n},Pc.lineEnd=function(){Pc.point=Pc.lineEnd=v}}function mr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function yr(n,t){function e(n,t){o>0?-Sa+ka>t&&(t=-Sa+ka):t>Sa-ka&&(t=Sa-ka);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(ba/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=B(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Sa]},e):Mr}function xr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ua(u)u;u++){for(;r>1&&W(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function Er(n,t){return n[0]-t[0]||n[1]-t[1]}function Ar(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Cr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Nr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function zr(){Gr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Bc.pop()||new zr;return t.site=n,t}function Tr(n){Yr(n),Vc.remove(n),Bc.push(n),Gr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&ua(e-c.circle.x)l;++l)s=a[l],c=a[l-1],Br(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Xr(c.site,s.site,null,u),Or(c),Or(s)}function Rr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Vc._;a;)if(r=Dr(a,o)-i,r>ka)a=a.L;else{if(u=i-Pr(a,o),!(u>ka)){r>-ka?(t=a.P,e=a):u>-ka?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if(Vc.insert(t,c),t||e){if(t===e)return Yr(t),e=Lr(t.site),Vc.insert(c,e),c.edge=e.edge=Xr(t.site,c.site),Or(t),Or(e),void 0;if(!e)return c.edge=Xr(t.site,c.site),void 0;Yr(t),Yr(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};Br(e.edge,s,p,M),c.edge=Xr(s,n,null,M),e.edge=Xr(n,p,null,M),Or(t),Or(e)}}function Dr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Pr(n,t){var e=n.N;if(e)return Dr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ur(n){this.site=n,this.edges=[]}function jr(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Zc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(ua(r-t)>ka||ua(u-e)>ka)&&(a.splice(o,0,new Wr($r(i.site,l,ua(r-f)ka?{x:f,y:ua(t-f)ka?{x:ua(e-p)ka?{x:h,y:ua(t-h)ka?{x:ua(e-g)=-Ea)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Wc.pop()||new Fr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=$c._;x;)if(m.yd||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.yg){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.xi&&(u=t.substring(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:lu(e,r)})),i=Kc.lastIndex;return ir;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function hu(n,t){for(var e,r=Zo.interpolators.length;--r>=0&&!(e=Zo.interpolators[r](n,t)););return e}function gu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(hu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function pu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function vu(n){return function(t){return 1-n(1-t)}}function du(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function mu(n){return n*n}function yu(n){return n*n*n}function xu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Mu(n){return function(t){return Math.pow(t,n)}}function _u(n){return 1-Math.cos(n*Sa)}function bu(n){return Math.pow(2,10*(n-1))}function wu(n){return 1-Math.sqrt(1-n*n)}function Su(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/wa*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*wa/t)}}function ku(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Eu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Au(n,t){n=Zo.hcl(n),t=Zo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Zo.hsl(n),t=Zo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ut(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){n=Zo.lab(n),t=Zo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function zu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(Ru(e,t,-u))||0;t[0]*e[1]180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:lu(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:lu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:lu(g[0],p[0])},{i:e-2,x:lu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i=0;)e.push(u[r])}function Bu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++oe;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ii(n){return n.reduce(oi,0)}function oi(n,t){return n+t[1]}function ai(n,t){return ci(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ci(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function si(n){return[Zo.min(n),Zo.max(n)]}function li(n,t){return n.value-t.value}function fi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function hi(n,t){n._pack_next=t,t._pack_prev=n}function gi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function pi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(vi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],yi(r,u,i),t(i),fi(r,i),r._pack_prev=i,fi(i,u),u=r._pack_next,o=3;s>o;o++){yi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(gi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!gi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(di)}}function vi(n){n._pack_next=n._pack_prev=n}function di(n){delete n._pack_next,delete n._pack_prev}function mi(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Si(n,t,e){return n.a.parent===t.parent?n.a:e}function ki(n){return 1+Zo.max(n,function(n){return n.y})}function Ei(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ai(n){var t=n.children;return t&&t.length?Ai(t[0]):n}function Ci(n){var t,e=n.children;return e&&(t=e.length)?Ci(e[t-1]):n}function Ni(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function zi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Li(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ti(n){return n.rangeExtent?n.rangeExtent():Li(n.range())}function qi(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Ri(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Di(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ss}function Pi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Pi:qi,c=r?Uu:Pu;return o=u(n,t,c,e),a=u(t,n,c,hu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(zu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Oi(n,t)},i.tickFormat=function(t,e){return Yi(n,t,e)},i.nice=function(t){return Hi(n,t),u()},i.copy=function(){return Ui(n,t,e,r)},u()}function ji(n,t){return Zo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Hi(n,t){return Ri(n,Di(Fi(n,t)[2]))}function Fi(n,t){null==t&&(t=10);var e=Li(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Oi(n,t){return Zo.range.apply(Zo,Fi(n,t))}function Yi(n,t,e){var r=Fi(n,t);if(e){var u=Ga.exec(e);if(u.shift(),"s"===u[8]){var i=Zo.formatPrefix(Math.max(ua(r[0]),ua(r[1])));return u[7]||(u[7]="."+Ii(i.scale(r[2]))),u[8]="f",e=Zo.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Zi(u[8],r)),e=u.join("")}else e=",."+Ii(r[2])+"f";return Zo.format(e)}function Ii(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Zi(n,t){var e=Ii(t[2]);return n in ls?Math.abs(e-Ii(Math.max(ua(t[0]),ua(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Vi(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Ri(r.map(u),e?Math:hs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Li(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++0;h--)o.push(i(s)*h);for(s=0;o[s]c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return fs;arguments.length<2?t=fs:"function"!=typeof t&&(t=Zo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Vi(n.copy(),t,e,r)},ji(o,n)}function Xi(n,t,e){function r(t){return n(u(t))}var u=$i(t),i=$i(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Oi(e,n)},r.tickFormat=function(n,t){return Yi(e,n,t)},r.nice=function(n){return r.domain(Hi(e,n))},r.exponent=function(o){return arguments.length?(u=$i(t=o),i=$i(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Xi(n.copy(),t,e)},ji(r,n)}function $i(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Bi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return Zo.range(n.length).map(function(n){return t+e*n})}var u,i,a;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new o;for(var i,a=-1,c=r.length;++an?[0/0,0/0]:[n>0?o[n-1]:e[0],nt?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ji(n,t,e)},u()}function Gi(n,t){function e(e){return e>=e?t[Zo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Gi(n,t)},e}function Ki(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Oi(n,t)},t.tickFormat=function(t,e){return Yi(n,t,e)},t.copy=function(){return Ki(n)},t}function Qi(n){return n.innerRadius}function no(n){return n.outerRadius}function to(n){return n.startAngle}function eo(n){return n.endAngle}function ro(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=bt(e),p=bt(r);++f1&&u.push("H",r[0]),u.join("")}function ao(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function So(n){return n.length<3?uo(n):n[0]+ho(n,wo(n))}function ko(n){for(var t,e,r,u=-1,i=n.length;++ue?s():(u.active=e,i.event&&i.event.start.call(n,l,t),i.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Zo.timer(function(){return p.c=c(r||1)?we:c,1},0,a),void 0)}function c(r){if(u.active!==e)return s();for(var o=r/g,a=f(o),c=v.length;c>0;)v[--c].call(n,a); +return o>=1?(i.event&&i.event.end.call(n,l,t),s()):void 0}function s(){return--u.count?delete u[e]:delete n.__transition__,1}var l=n.__data__,f=i.ease,h=i.delay,g=i.duration,p=Ba,v=[];return p.t=h+a,r>=h?o(r-h):(p.c=o,void 0)},0,a)}}function Uo(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function jo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Ho(n){return n.toISOString()}function Fo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Zo.bisect(Us,u);return i==Us.length?[t.year,Fi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Us[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=Oo(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Oo(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Li(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Oo(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Fo(n.copy(),t,e)},ji(r,n)}function Oo(n){return new Date(n)}function Yo(n){return JSON.parse(n.responseText)}function Io(n){var t=$o.createRange();return t.selectNode($o.body),t.createContextualFragment(n.responseText)}var Zo={version:"3.4.11"};Date.now||(Date.now=function(){return+new Date});var Vo=[].slice,Xo=function(n){return Vo.call(n)},$o=document,Bo=$o.documentElement,Wo=window;try{Xo(Bo.childNodes)[0].nodeType}catch(Jo){Xo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{$o.createElement("div").style.setProperty("opacity",0,"")}catch(Go){var Ko=Wo.Element.prototype,Qo=Ko.setAttribute,na=Ko.setAttributeNS,ta=Wo.CSSStyleDeclaration.prototype,ea=ta.setProperty;Ko.setAttribute=function(n,t){Qo.call(this,n,t+"")},Ko.setAttributeNS=function(n,t,e){na.call(this,n,t,e+"")},ta.setProperty=function(n,t,e){ea.call(this,n,t+"",e)}}Zo.ascending=n,Zo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Zo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ur&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ur&&(e=r)}return e},Zo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ue&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ue&&(e=r)}return e},Zo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=e);)e=u=void 0;for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=e);)e=void 0;for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},Zo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i1&&(e=e.map(r)),e=e.filter(t),e.length?Zo.quantile(e.sort(n),.5):void 0};var ra=e(n);Zo.bisectLeft=ra.left,Zo.bisect=Zo.bisectRight=ra.right,Zo.bisector=function(t){return e(1===t.length?function(e,r){return n(t(e),r)}:t)},Zo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Zo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Zo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Zo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,t=Zo.min(arguments,r),e=new Array(t);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ua=Math.abs;Zo.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/e)throw new Error("infinite range");var r,i=[],o=u(ua(e)),a=-1;if(n*=o,t*=o,e*=o,0>e)for(;(r=n+e*++a)>t;)i.push(r/o);else for(;(r=n+e*++a)=i.length)return r?r.call(u,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=i[c++],d=new o;++g=i.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],a=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(Zo.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return a[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},Zo.set=function(n){var t=new h;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},i(h,{has:a,add:function(n){return this[ia+n]=!0,n},remove:function(n){return n=ia+n,n in this&&delete this[n]},values:s,size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===oa&&n.call(this,t.substring(1))}}),Zo.behavior={},Zo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Zo.event=null,Zo.requote=function(n){return n.replace(ca,"\\$&")};var ca=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,sa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},la=function(n,t){return t.querySelector(n)},fa=function(n,t){return t.querySelectorAll(n)},ha=Bo.matches||Bo[p(Bo,"matchesSelector")],ga=function(n,t){return ha.call(n,t)};"function"==typeof Sizzle&&(la=function(n,t){return Sizzle(n,t)[0]||null},fa=Sizzle,ga=Sizzle.matchesSelector),Zo.selection=function(){return ma};var pa=Zo.selection.prototype=[];pa.select=function(n){var t,e,r,u,i=[];n=b(n);for(var o=-1,a=this.length;++o=0&&(e=n.substring(0,t),n=n.substring(t+1)),va.hasOwnProperty(e)?{space:va[e],local:n}:n}},pa.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Zo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(S(t,n[t]));return this}return this.each(S(n,t))},pa.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=A(n)).length,u=-1;if(t=e.classList){for(;++ur){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(z(e,n[e],t));return this}if(2>r)return Wo.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(z(n,t,e))},pa.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(L(t,n[t]));return this}return this.each(L(n,t))},pa.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},pa.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},pa.append=function(n){return n=T(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},pa.insert=function(n,t){return n=T(n),t=b(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},pa.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},pa.data=function(n,t){function e(n,e){var r,u,i,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new o,y=new o,x=[];for(r=-1;++rr;++r)p[r]=q(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,u,i=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++ii;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return _(u)},pa.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},pa.sort=function(n){n=D.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},pa.size=function(){var n=0;return this.each(function(){++n}),n};var da=[];Zo.selection.enter=U,Zo.selection.enter.prototype=da,da.append=pa.append,da.empty=pa.empty,da.node=pa.node,da.call=pa.call,da.size=pa.size,da.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(F(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(F(n,t,e))};var ya=Zo.map({mouseenter:"mouseover",mouseleave:"mouseout"});ya.forEach(function(n){"on"+n in $o&&ya.remove(n)});var xa="onselectstart"in $o?null:p(Bo.style,"userSelect"),Ma=0;Zo.mouse=function(n){return Z(n,x())};var _a=/WebKit/.test(Wo.navigator.userAgent)?-1:0;Zo.touches=function(n,t){return arguments.length<2&&(t=x().touches),t?Xo(t).map(function(t){var e=Z(n,t);return e.identifier=t.identifier,e}):[]},Zo.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",i)}function t(n,t,u,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-x[0],e=r[1]-x[1],p|=n|e,x=r,g({type:"drag",x:r[0]+s[0],y:r[1]+s[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&Zo.event.target===f),g({type:"dragend"}))}var s,l=this,f=Zo.event.target,h=l.parentNode,g=e.of(l,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=Zo.select(u()).on(i+d,a).on(o+d,c),y=I(),x=t(h,v);r?(s=r.apply(l,arguments),s=[s.x-x[0],s.y-x[1]]):s=[0,0],g({type:"dragstart"})}}var e=M(n,"drag","dragstart","dragend"),r=null,u=t(v,Zo.mouse,$,"mousemove","mouseup"),i=t(V,Zo.touch,X,"touchmove","touchend");return n.origin=function(t){return arguments.length?(r=t,n):r},Zo.rebind(n,e,"on")};var ba=Math.PI,wa=2*ba,Sa=ba/2,ka=1e-6,Ea=ka*ka,Aa=ba/180,Ca=180/ba,Na=Math.SQRT2,za=2,La=4;Zo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=Q(v),o=i/(za*h)*(e*nt(Na*t+v)-K(v));return[r+o*s,u+o*l,i*e/Q(Na*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Na*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+La*f)/(2*i*za*h),p=(c*c-i*i-La*f)/(2*c*za*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Na;return e.duration=1e3*y,e},Zo.behavior.zoom=function(){function n(n){n.on(A,s).on(Ra+".zoom",f).on("dblclick.zoom",h).on(z,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(x.range().map(function(n){return(n-S.x)/S.k}).map(x.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Zo.mouse(r),h),a(s)}function e(){f.on(C,null).on(N,null),g(l&&Zo.event.target===i),c(s)}var r=this,i=Zo.event.target,s=L.of(r,arguments),l=0,f=Zo.select(Wo).on(C,n).on(N,e),h=t(Zo.mouse(r)),g=I();H.call(r),o(s)}function l(){function n(){var n=Zo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){var t=Zo.event.target;Zo.select(t).on(M,i).on(_,f),b.push(t);for(var e=Zo.event.changedTouches,o=0,c=e.length;c>o;++o)v[e[o].identifier]=null;var s=n(),l=Date.now();if(1===s.length){if(500>l-m){var h=s[0],g=v[h.identifier];r(2*S.k),u(h,g),y(),a(p)}m=l}else if(s.length>1){var h=s[0],x=s[1],w=h[0]-x[0],k=h[1]-x[1];d=w*w+k*k}}function i(){for(var n,t,e,i,o=Zo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=d&&Math.sqrt(l/d);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}m=null,u(n,t),a(p)}function f(){if(Zo.event.touches.length){for(var t=Zo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}Zo.selectAll(b).on(x,null),w.on(A,s).on(z,l),k(),c(p)}var h,g=this,p=L.of(g,arguments),v={},d=0,x=".zoom-"+Zo.event.changedTouches[0].identifier,M="touchmove"+x,_="touchend"+x,b=[],w=Zo.select(g).on(A,null).on(z,e),k=I();H.call(g),e(),o(p)}function f(){var n=L.of(this,arguments);d?clearTimeout(d):(g=t(p=v||Zo.mouse(this)),H.call(this),o(n)),d=setTimeout(function(){d=null,c(n)},50),y(),r(Math.pow(2,.002*Ta())*S.k),u(p,g),a(n)}function h(){var n=L.of(this,arguments),e=Zo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Zo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var g,p,v,d,m,x,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=qa,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",z="touchstart.zoom",L=M(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=L.of(this,arguments),t=S;Ss?Zo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Zo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?qa:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,x=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Zo.rebind(n,L,"on")};var Ta,qa=[0,1/0],Ra="onwheel"in $o?(Ta=function(){return-Zo.event.deltaY*(Zo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in $o?(Ta=function(){return Zo.event.wheelDelta},"mousewheel"):(Ta=function(){return-Zo.event.detail},"MozMousePixelScroll");Zo.color=et,et.prototype.toString=function(){return this.rgb()+""},Zo.hsl=rt;var Da=rt.prototype=new et;Da.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,this.l/n)},Da.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,n*this.l)},Da.rgb=function(){return ut(this.h,this.s,this.l)},Zo.hcl=it;var Pa=it.prototype=new et;Pa.brighter=function(n){return new it(this.h,this.c,Math.min(100,this.l+Ua*(arguments.length?n:1)))},Pa.darker=function(n){return new it(this.h,this.c,Math.max(0,this.l-Ua*(arguments.length?n:1)))},Pa.rgb=function(){return ot(this.h,this.c,this.l).rgb()},Zo.lab=at;var Ua=18,ja=.95047,Ha=1,Fa=1.08883,Oa=at.prototype=new et;Oa.brighter=function(n){return new at(Math.min(100,this.l+Ua*(arguments.length?n:1)),this.a,this.b)},Oa.darker=function(n){return new at(Math.max(0,this.l-Ua*(arguments.length?n:1)),this.a,this.b)},Oa.rgb=function(){return ct(this.l,this.a,this.b)},Zo.rgb=gt;var Ya=gt.prototype=new et;Ya.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new gt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new gt(u,u,u)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new gt(n*this.r,n*this.g,n*this.b)},Ya.hsl=function(){return yt(this.r,this.g,this.b)},Ya.toString=function(){return"#"+dt(this.r)+dt(this.g)+dt(this.b)};var Ia=Zo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ia.forEach(function(n,t){Ia.set(n,pt(t))}),Zo.functor=bt,Zo.xhr=St(wt),Zo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=kt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new h,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Zo.csv=Zo.dsv(",","text/csv"),Zo.tsv=Zo.dsv(" ","text/tab-separated-values"),Zo.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=x().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return Z(n,r)};var Za,Va,Xa,$a,Ba,Wa=Wo[p(Wo,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Zo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Va?Va.n=i:Za=i,Va=i,Xa||($a=clearTimeout($a),Xa=1,Wa(At))},Zo.timer.flush=function(){Ct(),Nt()},Zo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ja=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Zo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Zo.round(n,zt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),Ja[8+e/3]};var Ga=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,Ka=Zo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Zo.round(n,zt(n,t))).toFixed(Math.max(0,Math.min(20,zt(n*(1+1e-15),t))))}}),Qa=Zo.time={},nc=Date;Rt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){tc.setUTCDate.apply(this._,arguments)},setDay:function(){tc.setUTCDay.apply(this._,arguments)},setFullYear:function(){tc.setUTCFullYear.apply(this._,arguments)},setHours:function(){tc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){tc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){tc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){tc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){tc.setUTCSeconds.apply(this._,arguments)},setTime:function(){tc.setTime.apply(this._,arguments)}};var tc=Date.prototype;Qa.year=Dt(function(n){return n=Qa.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),Qa.years=Qa.year.range,Qa.years.utc=Qa.year.utc.range,Qa.day=Dt(function(n){var t=new nc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),Qa.days=Qa.day.range,Qa.days.utc=Qa.day.utc.range,Qa.dayOfYear=function(n){var t=Qa.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=Qa[n]=Dt(function(n){return(n=Qa.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});Qa[n+"s"]=e.range,Qa[n+"s"].utc=e.utc.range,Qa[n+"OfYear"]=function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)}}),Qa.week=Qa.sunday,Qa.weeks=Qa.sunday.range,Qa.weeks.utc=Qa.sunday.utc.range,Qa.weekOfYear=Qa.sundayOfYear;var ec={"-":"",_:" ",0:"0"},rc=/^\s*\d+/,uc=/^%/;Zo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Ut(n)}};var ic=Zo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Zo.format=ic.numberFormat,Zo.geo={},ue.prototype={s:0,t:0,add:function(n){ie(n,this.t,oc),ie(oc.s,this.s,this),this.s?this.t+=oc.t:this.s=oc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var oc=new ue;Zo.geo.stream=function(n,t){n&&ac.hasOwnProperty(n.type)?ac[n.type](n,t):oe(n,t)};var ac={Feature:function(n,t){oe(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*ba+n:n,fc.lineStart=fc.lineEnd=fc.point=v}};Zo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=le([t*Aa,e*Aa]);if(m){var u=he(m,r),i=[u[1],-u[0],0],o=he(i,u);ve(o),o=de(o);var c=t-p,s=c>0?1:-1,v=o[0]*Ca*s,d=ua(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*Ca;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*Ca;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ua(r)>180?r+(r>0?360:-360):r}else v=n,d=e;fc.point(n,e),t(n,e)}function i(){fc.lineStart()}function o(){u(v,d),fc.lineEnd(),ua(y)>ka&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nlc?(l=-(h=180),f=-(g=90)):y>ka?g=90:-ka>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Zo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e); +for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Zo.geo.centroid=function(n){hc=gc=pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,wc);var t=Mc,e=_c,r=bc,u=t*t+e*e+r*r;return Ea>u&&(t=mc,e=yc,r=xc,ka>gc&&(t=pc,e=vc,r=dc),u=t*t+e*e+r*r,Ea>u)?[0/0,0/0]:[Math.atan2(e,t)*Ca,G(r/Math.sqrt(u))*Ca]};var hc,gc,pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc={sphere:v,point:ye,lineStart:Me,lineEnd:_e,polygonStart:function(){wc.lineStart=be},polygonEnd:function(){wc.lineStart=Me}},Sc=Ae(we,Te,Re,[-ba,-ba/2]),kc=1e9;Zo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ue(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Zo.geo.conicEqualArea=function(){return He(Fe)}).raw=Fe,Zo.geo.albers=function(){return Zo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Zo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Zo.geo.albers(),o=Zo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Zo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+ka,f+.12*s+ka],[l-.214*s-ka,f+.234*s-ka]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+ka,f+.166*s+ka],[l-.115*s-ka,f+.234*s-ka]]).stream(c).point,n},n.scale(1070)};var Ec,Ac,Cc,Nc,zc,Lc,Tc={point:v,lineStart:v,lineEnd:v,polygonStart:function(){Ac=0,Tc.lineStart=Oe},polygonEnd:function(){Tc.lineStart=Tc.lineEnd=Tc.point=v,Ec+=ua(Ac/2)}},qc={point:Ye,lineStart:v,lineEnd:v,polygonStart:v,polygonEnd:v},Rc={point:Ve,lineStart:Xe,lineEnd:$e,polygonStart:function(){Rc.lineStart=Be},polygonEnd:function(){Rc.point=Ve,Rc.lineStart=Xe,Rc.lineEnd=$e}};Zo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Zo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Ec=0,Zo.geo.stream(n,u(Tc)),Ec},n.centroid=function(n){return pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,u(Rc)),bc?[Mc/bc,_c/bc]:xc?[mc/xc,yc/xc]:dc?[pc/dc,vc/dc]:[0/0,0/0]},n.bounds=function(n){return zc=Lc=-(Cc=Nc=1/0),Zo.geo.stream(n,u(qc)),[[Cc,Nc],[zc,Lc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Ge(n):wt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ie:new We(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Zo.geo.albersUsa()).context(null)},Zo.geo.transform=function(n){return{stream:function(t){var e=new Ke(t);for(var r in n)e[r]=n[r];return e}}},Ke.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Zo.geo.projection=nr,Zo.geo.projectionMutator=tr,(Zo.geo.equirectangular=function(){return nr(rr)}).raw=rr.invert=rr,Zo.geo.rotation=function(n){function t(t){return t=n(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t}return n=ir(n[0]%360*Aa,n[1]*Aa,n.length>2?n[2]*Aa:0),t.invert=function(t){return t=n.invert(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t},t},ur.invert=rr,Zo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ir(-n[0]*Aa,-n[1]*Aa,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Ca,n[1]*=Ca}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=sr((t=+r)*Aa,u*Aa),n):t},n.precision=function(r){return arguments.length?(e=sr(t*Aa,(u=+r)*Aa),n):u},n.angle(90)},Zo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Aa,u=n[1]*Aa,i=t[1]*Aa,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Zo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Zo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Zo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Zo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ua(n%d)>ka}).map(l)).concat(Zo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ua(n%m)>ka}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=fr(a,o,90),f=hr(r,e,y),h=fr(s,c,90),g=hr(i,u,y),n):y},n.majorExtent([[-180,-90+ka],[180,90-ka]]).minorExtent([[-180,-80-ka],[180,80+ka]])},Zo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=gr,u=pr;return n.distance=function(){return Zo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Zo.geo.interpolate=function(n,t){return vr(n[0]*Aa,n[1]*Aa,t[0]*Aa,t[1]*Aa)},Zo.geo.length=function(n){return Dc=0,Zo.geo.stream(n,Pc),Dc};var Dc,Pc={sphere:v,point:v,lineStart:dr,lineEnd:v,polygonStart:v,polygonEnd:v},Uc=mr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Zo.geo.azimuthalEqualArea=function(){return nr(Uc)}).raw=Uc;var jc=mr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},wt);(Zo.geo.azimuthalEquidistant=function(){return nr(jc)}).raw=jc,(Zo.geo.conicConformal=function(){return He(yr)}).raw=yr,(Zo.geo.conicEquidistant=function(){return He(xr)}).raw=xr;var Hc=mr(function(n){return 1/n},Math.atan);(Zo.geo.gnomonic=function(){return nr(Hc)}).raw=Hc,Mr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Sa]},(Zo.geo.mercator=function(){return _r(Mr)}).raw=Mr;var Fc=mr(function(){return 1},Math.asin);(Zo.geo.orthographic=function(){return nr(Fc)}).raw=Fc;var Oc=mr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Zo.geo.stereographic=function(){return nr(Oc)}).raw=Oc,br.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Sa]},(Zo.geo.transverseMercator=function(){var n=_r(br),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=br,Zo.geom={},Zo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=bt(e),i=bt(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(Er),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=kr(a),l=kr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/ka)*ka,y:Math.round(o(n,t)/ka)*ka,i:t}})}var r=wr,u=Sr,i=r,o=u,a=Jc;return n?t(n):(t.links=function(n){return tu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return tu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Hr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=ou()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=bt(a),M=bt(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.xm&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=ou();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){au(n,k,v,d,m,y)},g=-1,null==t){for(;++g=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ns.get(e)||Qc,r=ts.get(r)||wt,pu(r(e.apply(null,Vo.call(arguments,1))))},Zo.interpolateHcl=Au,Zo.interpolateHsl=Cu,Zo.interpolateLab=Nu,Zo.interpolateRound=zu,Zo.transform=function(n){var t=$o.createElementNS(Zo.ns.prefix.svg,"g");return(Zo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:es)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var es={a:1,b:0,c:0,d:1,e:0,f:0};Zo.interpolateTransform=Du,Zo.layout={},Zo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Zo.event.x,n.py=Zo.event.y,a.resume()}var e,r,u,i,o,a={},c=Zo.dispatch("start","tick","end"),s=[1,1],l=.9,f=rs,h=us,g=-30,p=is,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Vu(t=Zo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Zo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++at;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Zo.behavior.drag().origin(wt).on("dragstart.force",Ou).on("drag.force",t).on("dragend.force",Yu)),arguments.length?(this.on("mouseover.force",Iu).on("mouseout.force",Zu).call(e),void 0):e},Zo.rebind(a,c,"on")};var rs=20,us=1,is=1/0;Zo.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(s=e.call(n,i,i.depth))&&(c=s.length)){for(var c,s,l;--c>=0;)o.push(l=s[c]),l.parent=i,l.depth=i.depth+1;r&&(i.value=0),i.children=s}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Bu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=Gu,e=Wu,r=Ju;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&($u(t,function(n){n.children&&(n.value=0)}),Bu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},Zo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++sg;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=wt,e=ei,r=ri,u=ti,i=Qu,o=ni;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:as.get(t)||ei,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:cs.get(t)||ri,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var as=Zo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ui),i=n.map(ii),o=Zo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Zo.range(n.length).reverse()},"default":ei}),cs=Zo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ri});Zo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=l[0]&&a<=l[1]&&(o=c[Zo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=si,u=ai;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=bt(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ci(n,t)}:bt(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Zo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Bu(a,function(n){n.r=+l(n.value)}),Bu(a,pi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;Bu(a,function(n){n.r+=f}),Bu(a,pi),Bu(a,function(n){n.r-=f})}return mi(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Zo.layout.hierarchy().sort(li),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Xu(n,e)},Zo.layout.tree=function(){function n(n,u){var l=o.call(this,n,u),f=l[0],h=t(f);if(Bu(h,e),h.parent.m=-h.z,$u(h,r),s)$u(f,i);else{var g=f,p=f,v=f;$u(f,function(n){n.xp.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);$u(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return l}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){wi(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],s=u.m,l=i.m,f=o.m,h=c.m;o=_i(o),u=Mi(u),o&&u;)c=Mi(c),i=_i(i),i.a=n,r=o.z+f-u.z-s+a(o._,u._),r>0&&(bi(Si(o,n,e),n,r),s+=r,l+=r),f+=o.m,s+=u.m,h+=c.m,l+=i.m;o&&!_i(i)&&(i.t=o,i.m+=f-l),u&&!Mi(c)&&(c.t=u,c.m+=s-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=Zo.layout.hierarchy().sort(null).value(null),a=xi,c=[1,1],s=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(s=null==(c=t)?i:null,n):s?null:c},n.nodeSize=function(t){return arguments.length?(s=null==(c=t)?null:i,n):s?c:null},Xu(n,o)},Zo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;Bu(c,function(n){var t=n.children;t&&t.length?(n.x=Ei(t),n.y=ki(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ai(c),f=Ci(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return Bu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Zo.layout.hierarchy().sort(null).value(null),e=xi,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Xu(n,t)},Zo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++oe&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++ie.dx)&&(l=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Zo.random.normal.apply(Zo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Zo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Zo.scale={};var ss={floor:wt,ceil:wt};Zo.scale.linear=function(){return Ui([0,1],[0,1],hu,!1)};var ls={s:1,g:1,p:1,r:1,e:1};Zo.scale.log=function(){return Vi(Zo.scale.linear().domain([0,1]),10,!0,[1,10])};var fs=Zo.format(".0e"),hs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Zo.scale.pow=function(){return Xi(Zo.scale.linear(),1,[0,1])},Zo.scale.sqrt=function(){return Zo.scale.pow().exponent(.5)},Zo.scale.ordinal=function(){return Bi([],{t:"range",a:[[]]})},Zo.scale.category10=function(){return Zo.scale.ordinal().range(gs)},Zo.scale.category20=function(){return Zo.scale.ordinal().range(ps)},Zo.scale.category20b=function(){return Zo.scale.ordinal().range(vs)},Zo.scale.category20c=function(){return Zo.scale.ordinal().range(ds)};var gs=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(vt),ps=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(vt),vs=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(vt),ds=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(vt);Zo.scale.quantile=function(){return Wi([],[])},Zo.scale.quantize=function(){return Ji(0,1,[0,1])},Zo.scale.threshold=function(){return Gi([.5],[0,1])},Zo.scale.identity=function(){return Ki([0,1])},Zo.svg={},Zo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ms,a=u.apply(this,arguments)+ms,c=(o>a&&(c=o,o=a,a=c),a-o),s=ba>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a); +return c>=ys?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=Qi,e=no,r=to,u=eo;return n.innerRadius=function(e){return arguments.length?(t=bt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=bt(t),n):e},n.startAngle=function(t){return arguments.length?(r=bt(t),n):r},n.endAngle=function(t){return arguments.length?(u=bt(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ms;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ms=-Sa,ys=wa-ka;Zo.svg.line=function(){return ro(wt)};var xs=Zo.map({linear:uo,"linear-closed":io,step:oo,"step-before":ao,"step-after":co,basis:po,"basis-open":vo,"basis-closed":mo,bundle:yo,cardinal:fo,"cardinal-open":so,"cardinal-closed":lo,monotone:So});xs.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Ms=[0,2/3,1/3,0],_s=[0,1/3,2/3,0],bs=[0,1/6,2/3,1/6];Zo.svg.line.radial=function(){var n=ro(ko);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},ao.reverse=co,co.reverse=ao,Zo.svg.area=function(){return Eo(wt)},Zo.svg.area.radial=function(){var n=Eo(ko);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Zo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ms,l=s.call(n,u,r)+ms;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>ba)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=gr,o=pr,a=Ao,c=to,s=eo;return n.radius=function(t){return arguments.length?(a=bt(t),n):a},n.source=function(t){return arguments.length?(i=bt(t),n):i},n.target=function(t){return arguments.length?(o=bt(t),n):o},n.startAngle=function(t){return arguments.length?(c=bt(t),n):c},n.endAngle=function(t){return arguments.length?(s=bt(t),n):s},n},Zo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=gr,e=pr,r=Co;return n.source=function(e){return arguments.length?(t=bt(e),n):t},n.target=function(t){return arguments.length?(e=bt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Zo.svg.diagonal.radial=function(){var n=Zo.svg.diagonal(),t=Co,e=n.projection;return n.projection=function(n){return arguments.length?e(No(t=n)):t},n},Zo.svg.symbol=function(){function n(n,r){return(ws.get(t.call(this,n,r))||To)(e.call(this,n,r))}var t=Lo,e=zo;return n.type=function(e){return arguments.length?(t=bt(e),n):t},n.size=function(t){return arguments.length?(e=bt(t),n):e},n};var ws=Zo.map({circle:To,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*As)),e=t*As;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Zo.svg.symbolTypes=ws.keys();var Ss,ks,Es=Math.sqrt(3),As=Math.tan(30*Aa),Cs=[],Ns=0;Cs.call=pa.call,Cs.empty=pa.empty,Cs.node=pa.node,Cs.size=pa.size,Zo.transition=function(n){return arguments.length?Ss?n.transition():n:ma.transition()},Zo.transition.prototype=Cs,Cs.select=function(n){var t,e,r,u=this.id,i=[];n=b(n);for(var o=-1,a=this.length;++oi;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return qo(u,this.id)},Cs.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):P(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Cs.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Du:hu,a=Zo.ns.qualify(n);return Ro(this,"attr."+n,t,a.local?i:u)},Cs.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Zo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Cs.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Wo.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=hu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Ro(this,"style."+n,t,u)},Cs.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Wo.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Cs.text=function(n){return Ro(this,"text",n,Do)},Cs.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Cs.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Zo.ease.apply(Zo,arguments)),P(this,function(e){e.__transition__[t].ease=n}))},Cs.delay=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].delay:P(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Cs.duration=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].duration:P(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Cs.each=function(n,t){var e=this.id;if(arguments.length<2){var r=ks,u=Ss;Ss=e,P(this,function(t,r,u){ks=t.__transition__[e],n.call(t,t.__data__,r,u)}),ks=r,Ss=u}else P(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Zo.dispatch("start","end"))).on(n,t)});return this},Cs.transition=function(){for(var n,t,e,r,u=this.id,i=++Ns,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,Po(e,s,i,r)),n.push(e)}return qo(o,i)},Zo.svg.axis=function(){function n(n){n.each(function(){var n,s=Zo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):wt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",ka),d=Zo.transition(p.exit()).style("opacity",ka).remove(),m=Zo.transition(p.order()).style("opacity",1),y=Ti(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Zo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Uo,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Uo,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=jo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=jo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Zo.scale.linear(),r=zs,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Ls?t+"":zs,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var zs="bottom",Ls={top:1,right:1,bottom:1,left:1};Zo.svg.brush=function(){function n(i){i.each(function(){var i=Zo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,wt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Ts[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Zo.transition(i),h=Zo.transition(o);c&&(l=Ti(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ti(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Zo.event.keyCode&&(C||(x=null,z[0]-=l[1],z[1]-=f[1],C=2),y())}function p(){32==Zo.event.keyCode&&2==C&&(z[0]+=l[1],z[1]+=f[1],C=0,y())}function v(){var n=Zo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Zo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),z[0]=l[+(n[0]p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function m(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Zo.select("body").style("cursor",null),L.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Zo.select(Zo.event.target),w=a.of(_,arguments),S=Zo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=I(),z=Zo.mouse(_),L=Zo.select(Wo).on("keydown.brush",u).on("keyup.brush",p);if(Zo.event.changedTouches?L.on("touchmove.brush",v).on("touchend.brush",m):L.on("mousemove.brush",v).on("mouseup.brush",m),S.interrupt().selectAll("*").interrupt(),C)z[0]=l[0]-z[0],z[1]=f[0]-z[1];else if(k){var T=+/w$/.test(k),q=+/^n/.test(k);M=[l[1-T]-z[0],f[1-q]-z[1]],z[0]=l[T],z[1]=f[q]}else Zo.event.altKey&&(x=z.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Zo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=M(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=qs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,Ss?Zo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=gu(l,t.x),r=gu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=qs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=qs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Zo.rebind(n,a,"on")};var Ts={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},qs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Rs=Qa.format=ic.timeFormat,Ds=Rs.utc,Ps=Ds("%Y-%m-%dT%H:%M:%S.%LZ");Rs.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Ho:Ps,Ho.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Ho.toString=Ps.toString,Qa.second=Dt(function(n){return new nc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),Qa.seconds=Qa.second.range,Qa.seconds.utc=Qa.second.utc.range,Qa.minute=Dt(function(n){return new nc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),Qa.minutes=Qa.minute.range,Qa.minutes.utc=Qa.minute.utc.range,Qa.hour=Dt(function(n){var t=n.getTimezoneOffset()/60;return new nc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),Qa.hours=Qa.hour.range,Qa.hours.utc=Qa.hour.utc.range,Qa.month=Dt(function(n){return n=Qa.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),Qa.months=Qa.month.range,Qa.months.utc=Qa.month.utc.range;var Us=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],js=[[Qa.second,1],[Qa.second,5],[Qa.second,15],[Qa.second,30],[Qa.minute,1],[Qa.minute,5],[Qa.minute,15],[Qa.minute,30],[Qa.hour,1],[Qa.hour,3],[Qa.hour,6],[Qa.hour,12],[Qa.day,1],[Qa.day,2],[Qa.week,1],[Qa.month,1],[Qa.month,3],[Qa.year,1]],Hs=Rs.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",we]]),Fs={range:function(n,t,e){return Zo.range(Math.ceil(n/e)*e,+t,e).map(Oo)},floor:wt,ceil:wt};js.year=Qa.year,Qa.scale=function(){return Fo(Zo.scale.linear(),js,Hs)};var Os=js.map(function(n){return[n[0].utc,n[1]]}),Ys=Ds.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",we]]);Os.year=Qa.year.utc,Qa.scale.utc=function(){return Fo(Zo.scale.linear(),Os,Ys)},Zo.text=St(function(n){return n.responseText}),Zo.json=function(n,t){return kt(n,"application/json",Yo,t)},Zo.html=function(n,t){return kt(n,"text/html",Io,t)},Zo.xml=St(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Zo):"object"==typeof module&&module.exports&&(module.exports=Zo),this.d3=Zo}(); \ No newline at end of file diff --git a/gulliver/js/d3/d3.tip.js b/gulliver/js/d3/d3.tip.js new file mode 100644 index 000000000..e37254fd6 --- /dev/null +++ b/gulliver/js/d3/d3.tip.js @@ -0,0 +1,272 @@ +d3.tip = function() { + var direction = d3_tip_direction, + offset = d3_tip_offset, + html = d3_tip_html, + node = initNode(), + svg = null, + point = null, + target = null + + function tip(vis) { + svg = getSVGNode(vis) + point = svg.createSVGPoint() + document.body.appendChild(node) + } + + // Public - show the tooltip on the screen + // + // Returns a tip + tip.show = function() { + var args = Array.prototype.slice.call(arguments) + if(args[args.length - 1] instanceof SVGElement) target = args.pop() + + var content = html.apply(this, args), + poffset = offset.apply(this, args), + dir = direction.apply(this, args), + nodel = d3.select(node), i = 0, + coords + + nodel.html(content) + .style({ opacity: 1, 'pointer-events': 'all' }) + + while(i--) nodel.classed(directions[i], false) + coords = direction_callbacks.get(dir).apply(this) + nodel.classed(dir, true).style({ + top: (coords.top + poffset[0]) + 'px', + left: (coords.left + poffset[1]) + 'px' + }) + + return tip + } + + // Public - hide the tooltip + // + // Returns a tip + tip.hide = function() { + nodel = d3.select(node) + nodel.style({ opacity: 0, 'pointer-events': 'none' }) + return tip + } + + // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value. + // + // n - name of the attribute + // v - value of the attribute + // + // Returns tip or attribute value + tip.attr = function(n, v) { + if (arguments.length < 2 && typeof n === 'string') { + return d3.select(node).attr(n) + } else { + var args = Array.prototype.slice.call(arguments) + d3.selection.prototype.attr.apply(d3.select(node), args) + } + + return tip + } + + // Public: Proxy style calls to the d3 tip container. Sets or gets a style value. + // + // n - name of the property + // v - value of the property + // + // Returns tip or style property value + tip.style = function(n, v) { + if (arguments.length < 2 && typeof n === 'string') { + return d3.select(node).style(n) + } else { + var args = Array.prototype.slice.call(arguments) + d3.selection.prototype.style.apply(d3.select(node), args) + } + + return tip + } + + // Public: Set or get the direction of the tooltip + // + // v - One of n(north), s(south), e(east), or w(west), nw(northwest), + // sw(southwest), ne(northeast) or se(southeast) + // + // Returns tip or direction + tip.direction = function(v) { + if (!arguments.length) return direction + direction = v == null ? v : d3.functor(v) + + return tip + } + + // Public: Sets or gets the offset of the tip + // + // v - Array of [x, y] offset + // + // Returns offset or + tip.offset = function(v) { + if (!arguments.length) return offset + offset = v == null ? v : d3.functor(v) + + return tip + } + + // Public: sets or gets the html value of the tooltip + // + // v - String value of the tip + // + // Returns html value or tip + tip.html = function(v) { + if (!arguments.length) return html + html = v == null ? v : d3.functor(v) + + return tip + } + + function d3_tip_direction() { return 'n' } + function d3_tip_offset() { return [0, 0] } + function d3_tip_html() { return ' ' } + + var direction_callbacks = d3.map({ + n: direction_n, + s: direction_s, + e: direction_e, + w: direction_w, + nw: direction_nw, + ne: direction_ne, + sw: direction_sw, + se: direction_se + }), + + directions = direction_callbacks.keys() + + function direction_n() { + var bbox = getScreenBBox() + return { + top: bbox.n.y - node.offsetHeight, + left: bbox.n.x - node.offsetWidth / 2 + } + } + + function direction_s() { + var bbox = getScreenBBox() + return { + top: bbox.s.y, + left: bbox.s.x - node.offsetWidth / 2 + } + } + + function direction_e() { + var bbox = getScreenBBox() + return { + top: bbox.e.y - node.offsetHeight / 2, + left: bbox.e.x + } + } + + function direction_w() { + var bbox = getScreenBBox() + return { + top: bbox.w.y - node.offsetHeight / 2, + left: bbox.w.x - node.offsetWidth + } + } + + function direction_nw() { + var bbox = getScreenBBox() + return { + top: bbox.nw.y - node.offsetHeight, + left: bbox.nw.x - node.offsetWidth + } + } + + function direction_ne() { + var bbox = getScreenBBox() + return { + top: bbox.ne.y - node.offsetHeight, + left: bbox.ne.x + } + } + + function direction_sw() { + var bbox = getScreenBBox() + return { + top: bbox.sw.y, + left: bbox.sw.x - node.offsetWidth + } + } + + function direction_se() { + var bbox = getScreenBBox() + return { + top: bbox.se.y, + left: bbox.e.x + } + } + + function initNode() { + var node = d3.select(document.createElement('div')) + node.style({ + position: 'absolute', + opacity: 0, + pointerEvents: 'none', + boxSizing: 'border-box' + }) + + return node.node() + } + + function getSVGNode(el) { + el = el.node() + if(el.tagName.toLowerCase() == 'svg') + return el + + return el.ownerSVGElement + } + + // Private - gets the screen coordinates of a shape + // + // Given a shape on the screen, will return an SVGPoint for the directions + // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest), + // sw(southwest). + // + // +-+-+ + // | | + // + + + // | | + // +-+-+ + // + // Returns an Object {n, s, e, w, nw, sw, ne, se} + function getScreenBBox() { + var targetel = target || d3.event.target, + bbox = {}, + matrix = targetel.getScreenCTM(), + tbbox = targetel.getBBox(), + width = tbbox.width, + height = tbbox.height, + x = tbbox.x, + y = tbbox.y, + scrollTop = document.documentElement.scrollTop || document.body.scrollTop, + scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft + + + point.x = x + scrollLeft + point.y = y + scrollTop + bbox.nw = point.matrixTransform(matrix) + point.x += width + bbox.ne = point.matrixTransform(matrix) + point.y += height + bbox.se = point.matrixTransform(matrix) + point.x -= width + bbox.sw = point.matrixTransform(matrix) + point.y -= height / 2 + bbox.w = point.matrixTransform(matrix) + point.x += width + bbox.e = point.matrixTransform(matrix) + point.x -= width / 2 + point.y -= height / 2 + bbox.n = point.matrixTransform(matrix) + point.y += height + bbox.s = point.matrixTransform(matrix) + + return bbox + } + + return tip +}; diff --git a/gulliver/js/gridstack/gridstack.js b/gulliver/js/gridstack/gridstack.js new file mode 100644 index 000000000..5783e88fc --- /dev/null +++ b/gulliver/js/gridstack/gridstack.js @@ -0,0 +1,712 @@ +(function (scope, _) { + + var Utils = { + is_intercepted: function (a, b) { + return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y); + }, + + sort: function (nodes, dir, width) { + width = width || _.chain(nodes).map(function (node) { return node.x + node.width; }).max().value(); + dir = dir != -1 ? 1 : -1; + return _.sortBy(nodes, function (n) { return dir * (n.x + n.y * width); }); + }, + + create_stylesheet: function () { + var style = document.createElement("style"); + + // style.setAttribute("media", "screen") + // style.setAttribute("media", "only screen and (max-width : 1024px)") + + // WebKit hack :( + style.appendChild(document.createTextNode("")); + + document.head.appendChild(style); + + return style.sheet; + }, + + toBool: function (v) { + if (typeof v == 'boolean') + return v; + if (typeof v == 'string') { + v = v.toLowerCase(); + return !(v == '' || v == 'no' || v == 'false' || v == '0'); + } + return Boolean(v); + } + }; + + var id_seq = 0; + + var GridStackEngine = function (width, onchange, float, height, items) { + this.width = width; + this.float = float || false; + this.height = height || 0; + + this.nodes = items || []; + this.onchange = onchange || function () {}; + }; + + GridStackEngine.prototype._fix_collisions = function (node) { + this._sort_nodes(-1); + + while (true) { + var collision_node = _.find(this.nodes, function (n) { + return n != node && Utils.is_intercepted(n, node); + }, this); + if (typeof collision_node == 'undefined') { + return; + } + this.move_node(collision_node, collision_node.x, node.y + node.height, + collision_node.width, collision_node.height, true); + } + }; + + GridStackEngine.prototype._sort_nodes = function (dir) { + this.nodes = Utils.sort(this.nodes, dir, this.width); + }; + + GridStackEngine.prototype._pack_nodes = function () { + this._sort_nodes(); + + if (this.float) { + _.each(this.nodes, function (n, i) { + if (n._updating || typeof n._orig_y == 'undefined' || n.y == n._orig_y) + return; + + var new_y = n.y; + while (new_y >= n._orig_y) { + var collision_node = _.chain(this.nodes) + .find(function (bn) { + return n != bn && Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn); + }) + .value(); + + if (!collision_node) { + n._dirty = true; + n.y = new_y; + } + --new_y; + } + }, this); + } + else { + _.each(this.nodes, function (n, i) { + if (n.locked) + return; + while (n.y > 0) { + var new_y = n.y - 1; + var can_be_moved = i == 0; + + if (i > 0) { + var collision_node = _.chain(this.nodes) + .first(i) + .find(function (bn) { + return Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn); + }) + .value(); + can_be_moved = typeof collision_node == 'undefined'; + } + + if (!can_be_moved) { + break; + } + n._dirty = n.y != new_y; + n.y = new_y; + } + }, this); + } + }; + + GridStackEngine.prototype._prepare_node = function (node, resizing) { + node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0 }); + + node.x = parseInt('' + node.x); + node.y = parseInt('' + node.y); + node.width = parseInt('' + node.width); + node.height = parseInt('' + node.height); + node.auto_position = node.auto_position || false; + node.no_resize = node.no_resize || false; + node.no_move = node.no_move || false; + + if (node.width > this.width) { + node.width = this.width; + } + else if (node.width < 1) { + node.width = 1; + } + + if (node.height < 1) { + node.height = 1; + } + + if (node.x < 0) { + node.x = 0; + } + + if (node.x + node.width > this.width) { + if (resizing) { + node.width = this.width - node.x; + } + else { + node.x = this.width - node.width; + } + } + + if (node.y < 0) { + node.y = 0; + } + + return node; + }; + + GridStackEngine.prototype._notify = function () { + var deleted_nodes = Array.prototype.slice.call(arguments, 1).concat(this.get_dirty_nodes()); + deleted_nodes = deleted_nodes.concat(this.get_dirty_nodes()); + this.onchange(deleted_nodes); + }; + + GridStackEngine.prototype.clean_nodes = function () { + _.each(this.nodes, function (n) {n._dirty = false }); + }; + + GridStackEngine.prototype.get_dirty_nodes = function () { + return _.filter(this.nodes, function (n) { return n._dirty; }); + }; + + GridStackEngine.prototype.add_node = function(node) { + node = this._prepare_node(node); + + if (typeof node.max_width != 'undefined') node.width = Math.min(node.width, node.max_width); + if (typeof node.max_height != 'undefined') node.height = Math.min(node.height, node.max_height); + if (typeof node.min_width != 'undefined') node.width = Math.max(node.width, node.min_width); + if (typeof node.min_height != 'undefined') node.height = Math.max(node.height, node.min_height); + + node._id = ++id_seq; + node._dirty = true; + + if (node.auto_position) { + this._sort_nodes(); + + for (var i = 0; ; ++i) { + var x = i % this.width, y = Math.floor(i / this.width); + if (x + node.width > this.width) { + continue; + } + if (!_.find(this.nodes, function (n) { + return Utils.is_intercepted({x: x, y: y, width: node.width, height: node.height}, n); + })) { + node.x = x; + node.y = y; + break; + } + } + } + + this.nodes.push(node); + + this._fix_collisions(node); + this._pack_nodes(); + this._notify(); + return node; + }; + + GridStackEngine.prototype.remove_node = function (node) { + node._id = null; + this.nodes = _.without(this.nodes, node); + this._pack_nodes(); + this._notify(node); + }; + + GridStackEngine.prototype.can_move_node = function (node, x, y, width, height) { + var has_locked = Boolean(_.find(this.nodes, function (n) { return n.locked })); + + if (!this.height && !has_locked) + return true; + + var cloned_node; + var clone = new GridStackEngine( + this.width, + null, + this.float, + 0, + _.map(this.nodes, function (n) { if (n == node) { cloned_node = $.extend({}, n); return cloned_node; } return $.extend({}, n) })); + + clone.move_node(cloned_node, x, y, width, height); + + var res = true; + + if (has_locked) + res &= !Boolean(_.find(clone.nodes, function (n) { return n != cloned_node && Boolean(n.locked) && Boolean(n._dirty); })); + if (this.height) + res &= clone.get_grid_height() <= this.height; + + return res; + }; + + GridStackEngine.prototype.can_be_placed_with_respect_to_height = function (node) { + if (!this.height) + return true; + + var clone = new GridStackEngine( + this.width, + null, + this.float, + 0, + _.map(this.nodes, function (n) { return $.extend({}, n) })); + clone.add_node(node); + return clone.get_grid_height() <= this.height; + }; + + GridStackEngine.prototype.move_node = function (node, x, y, width, height, no_pack) { + if (typeof x != 'number') x = node.x; + if (typeof y != 'number') y = node.y; + if (typeof width != 'number') width = node.width; + if (typeof height != 'number') height = node.height; + + if (typeof node.max_width != 'undefined') width = Math.min(width, node.max_width); + if (typeof node.max_height != 'undefined') height = Math.min(height, node.max_height); + if (typeof node.min_width != 'undefined') width = Math.max(width, node.min_width); + if (typeof node.min_height != 'undefined') height = Math.max(height, node.min_height); + + if (node.x == x && node.y == y && node.width == width && node.height == height) { + return node; + } + + var resizing = node.width != width; + node._dirty = true; + + node.x = x; + node.y = y; + node.width = width; + node.height = height; + + node = this._prepare_node(node, resizing); + + this._fix_collisions(node); + if (!no_pack) { + this._pack_nodes(); + this._notify(); + } + return node; + }; + + GridStackEngine.prototype.get_grid_height = function () { + return _.reduce(this.nodes, function (memo, n) { return Math.max(memo, n.y + n.height); }, 0); + }; + + GridStackEngine.prototype.begin_update = function (node) { + _.each(this.nodes, function (n) { + n._orig_y = n.y; + }); + node._updating = true; + }; + + GridStackEngine.prototype.end_update = function () { + var n = _.find(this.nodes, function (n) { return n._updating; }); + if (n) { + n._updating = false; + } + }; + + var GridStack = function (el, opts) { + var self = this, one_column_mode; + + this.container = $(el); + + this.opts = _.defaults(opts || {}, { + width: parseInt(this.container.attr('data-gs-width')) || 12, + height: parseInt(this.container.attr('data-gs-height')) || 0, + item_class: 'grid-stack-item', + placeholder_class: 'grid-stack-placeholder', + handle: '.grid-stack-item-content', + cell_height: 60, + vertical_margin: 20, + auto: true, + min_width: 768, + float: false, + _class: 'grid-stack-' + (Math.random() * 10000).toFixed(0), + animate: Boolean(this.container.attr('data-gs-animate')) || false + }); + + this.container.addClass(this.opts._class); + this._styles = Utils.create_stylesheet(); + this._styles._max = 0; + + this.grid = new GridStackEngine(this.opts.width, function (nodes) { + var max_height = 0; + _.each(nodes, function (n) { + if (n._id == null) { + n.el.remove(); + } + else { + n.el + .attr('data-gs-x', n.x) + .attr('data-gs-y', n.y) + .attr('data-gs-width', n.width) + .attr('data-gs-height', n.height); + max_height = Math.max(max_height, n.y + n.height); + } + }); + self._update_styles(max_height + 10); + }, this.opts.float, this.opts.height); + + if (this.opts.auto) { + this.container.find('.' + this.opts.item_class).each(function (index, el) { + self._prepare_element(el); + }); + } + + this.set_animation(this.opts.animate); + + this.placeholder = $('
').hide(); + this.container.append(this.placeholder); + this.container.height((this.grid.get_grid_height()) * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin); + + var on_resize_handler = function () { + if (self._is_one_column_mode()) { + if (one_column_mode) + return; + + one_column_mode = true; + + _.each(self.grid.nodes, function (node) { + if (!node.no_move) { + node.el.draggable('disable'); + } + if (!node.no_resize) { + node.el.resizable('disable'); + } + }); + } + else { + if (!one_column_mode) + return; + + one_column_mode = false; + + _.each(self.grid.nodes, function (node) { + if (!node.no_move) { + node.el.draggable('enable'); + } + if (!node.no_resize) { + node.el.resizable('enable'); + } + }); + } + }; + + $(window).resize(on_resize_handler); + on_resize_handler(); + }; + + GridStack.prototype._update_styles = function (max_height) { + if (typeof max_height == 'undefined') { + max_height = this._styles._max; + this._styles._max = 0; + while (this._styles.rules.length) { + this._styles.removeRule(0); + } + this._update_container_height(); + } + + if (max_height > this._styles._max) { + for (var i = this._styles._max; i < max_height; ++i) { + var css; + css = '.' + this.opts._class + ' .' + this.opts.item_class + '[data-gs-height="' + (i + 1) + '"] { height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px; }'; + this._styles.insertRule(css, i); + css = '.' + this.opts._class + ' .' + this.opts.item_class + '[data-gs-y="' + (i) + '"] { top: ' + (this.opts.cell_height * i + this.opts.vertical_margin * i) + 'px; }'; + this._styles.insertRule(css, i); + } + this._styles._max = max_height; + } + }; + + GridStack.prototype._update_container_height = function () { + this.container.height(this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin); + }; + + GridStack.prototype._is_one_column_mode = function () { + return $(window).width() <= this.opts.min_width; + }; + + GridStack.prototype._prepare_element = function (el) { + var self = this; + el = $(el); + + el.addClass(this.opts.item_class); + + var node = self.grid.add_node({ + x: el.attr('data-gs-x'), + y: el.attr('data-gs-y'), + width: el.attr('data-gs-width'), + height: el.attr('data-gs-height'), + max_width: el.attr('data-gs-max-width'), + min_width: el.attr('data-gs-min-width'), + max_height: el.attr('data-gs-max-height') || 100, + min_height: el.attr('data-gs-min-height'), + auto_position: Utils.toBool(el.attr('data-gs-auto-position')), + no_resize: Utils.toBool(el.attr('data-gs-no-resize')), + no_move: Utils.toBool(el.attr('data-gs-no-move')), + locked: Utils.toBool(el.attr('data-gs-locked')), + el: el + }); + el.data('_gridstack_node', node); + + var cell_width, cell_height; + + var on_start_moving = function (event, ui) { + var o = $(this); + self.grid.clean_nodes(); + self.grid.begin_update(node); + cell_width = Math.ceil(o.outerWidth() / o.attr('data-gs-width')); + cell_height = self.opts.cell_height + self.opts.vertical_margin; + self.placeholder + .attr('data-gs-x', o.attr('data-gs-x')) + .attr('data-gs-y', o.attr('data-gs-y')) + .attr('data-gs-width', o.attr('data-gs-width')) + .attr('data-gs-height', o.attr('data-gs-height')) + .show(); + node.el = self.placeholder; + }; + + var on_end_moving = function (event, ui) { + var o = $(this); + node.el = o; + self.placeholder.hide(); + o + .attr('data-gs-x', node.x) + .attr('data-gs-y', node.y) + .attr('data-gs-width', node.width) + .attr('data-gs-height', node.height) + .removeAttr('style'); + self._update_container_height(); + self.container.trigger('change', [self.grid.get_dirty_nodes()]); + + self.grid.end_update(); + + self.grid._sort_nodes(); + setTimeout(function() { //if animating, delay detaching & reattaching all elements until animation finishes + _.each(self.grid.nodes, function (node) { + node.el.detach(); + self.container.append(node.el); + }); + }, (self.opts.animate ? 300 : 0)); + }; + + el.draggable({ + handle: this.opts.handle, + scroll: true, + appendTo: 'body', + + start: on_start_moving, + stop: on_end_moving, + drag: function (event, ui) { + var x = Math.round(ui.position.left / cell_width), + y = Math.floor((ui.position.top + cell_height/2) / cell_height); + if (!self.grid.can_move_node(node, x, y, node.width, node.height)) { + return; + } + self.grid.move_node(node, x, y); + self._update_container_height(); + } + }).resizable({ + autoHide: true, + handles: 'se', + minHeight: this.opts.cell_height - 10, + minWidth: 70, + + start: on_start_moving, + stop: on_end_moving, + resize: function (event, ui) { + var width = Math.round(ui.size.width / cell_width), + height = Math.round(ui.size.height / cell_height); + if (!self.grid.can_move_node(node, node.x, node.y, width, height)) { + return; + } + self.grid.move_node(node, node.x, node.y, width, height); + self._update_container_height(); + } + }); + + if (node.no_move || this._is_one_column_mode()) { + el.draggable('disable'); + } + + if (node.no_resize || this._is_one_column_mode()) { + el.resizable('disable'); + } + + el.attr('data-gs-locked', node.locked ? 'yes' : null); + }; + + GridStack.prototype.set_animation = function (enable) { + if (enable) { + this.container.addClass('grid-stack-animate'); + } + else { + this.container.removeClass('grid-stack-animate'); + } + }; + + GridStack.prototype.add_widget = function (el, x, y, width, height, auto_position) { + el = $(el); + if (typeof x != 'undefined') el.attr('data-gs-x', x); + if (typeof y != 'undefined') el.attr('data-gs-y', y); + if (typeof width != 'undefined') el.attr('data-gs-width', width); + if (typeof height != 'undefined') el.attr('data-gs-height', height); + if (typeof auto_position != 'undefined') el.attr('data-gs-auto-position', auto_position ? 'yes' : null); + this.container.append(el); + this._prepare_element(el); + this._update_container_height(); + }; + + GridStack.prototype.will_it_fit = function (x, y, width, height, auto_position) { + var node = {x: x, y: y, width: width, height: height, auto_position: auto_position}; + return this.grid.can_be_placed_with_respect_to_height(node); + }; + + GridStack.prototype.remove_widget = function (el) { + el = $(el); + var node = el.data('_gridstack_node'); + this.grid.remove_node(node); + el.remove(); + this._update_container_height(); + }; + + GridStack.prototype.remove_all = function () { + _.each(this.grid.nodes, function (node) { + node.el.remove(); + }); + this.grid.nodes = []; + this._update_container_height(); + }; + + GridStack.prototype.resizable = function (el, val) { + el = $(el); + el.each(function (index, el) { + el = $(el); + var node = el.data('_gridstack_node'); + if (typeof node == 'undefined') { + return; + } + + node.no_resize = !(val || false); + if (node.no_resize) { + el.resizable('disable'); + } + else { + el.resizable('enable'); + } + }); + return this; + }; + + GridStack.prototype.movable = function (el, val) { + el = $(el); + el.each(function (index, el) { + el = $(el); + var node = el.data('_gridstack_node'); + if (typeof node == 'undefined') { + return; + } + + node.no_move = !(val || false); + if (node.no_move) { + el.draggable('disable'); + } + else { + el.draggable('enable'); + } + }); + return this; + }; + + GridStack.prototype.locked = function (el, val) { + el = $(el); + el.each(function (index, el) { + el = $(el); + var node = el.data('_gridstack_node'); + if (typeof node == 'undefined') { + return; + } + + node.locked = (val || false); + el.attr('data-gs-locked', node.locked ? 'yes' : null); + }); + return this; + }; + + GridStack.prototype._update_element = function (el, callback) { + el = $(el).first(); + var node = el.data('_gridstack_node'); + if (typeof node == 'undefined') { + return; + } + + var self = this; + + self.grid.clean_nodes(); + self.grid.begin_update(node); + + callback.call(this, el, node); + + self._update_container_height(); + self.container.trigger('change', [self.grid.get_dirty_nodes()]); + + self.grid.end_update(); + + self.grid._sort_nodes(); + _.each(self.grid.nodes, function (node) { + node.el.detach(); + self.container.append(node.el); + }); + }; + + GridStack.prototype.resize = function (el, width, height) { + this._update_element(el, function (el, node) { + width = (width != null && typeof width != 'undefined') ? width : node.width; + height = (height != null && typeof height != 'undefined') ? height : node.height; + + this.grid.move_node(node, node.x, node.y, width, height); + }); + }; + + GridStack.prototype.move = function (el, x, y) { + this._update_element(el, function (el, node) { + x = (x != null && typeof x != 'undefined') ? x : node.x; + y = (y != null && typeof y != 'undefined') ? y : node.y; + + this.grid.move_node(node, x, y, node.width, node.height); + }); + }; + + GridStack.prototype.cell_height = function (val) { + if (typeof val == 'undefined') { + return this.opts.cell_height; + } + val = parseInt(val); + if (val == this.opts.cell_height) + return; + this.opts.cell_height = val || this.opts.cell_height; + this._update_styles(); + }; + + GridStack.prototype.cell_width = function () { + var o = this.container.find('.' + this.opts.item_class).first(); + return Math.ceil(o.outerWidth() / o.attr('data-gs-width')); + }; + + scope.GridStackUI = GridStack; + + scope.GridStackUI.Utils = Utils; + + $.fn.gridstack = function (opts) { + return this.each(function () { + if (!$(this).data('gridstack')) { + $(this).data('gridstack', new GridStack(this, opts)); + } + }); + }; + +})(window, _); diff --git a/gulliver/js/jquery/jquery-1.8.2.min.js b/gulliver/js/jquery/jquery-1.8.2.min.js new file mode 100644 index 000000000..bc3fbc81b --- /dev/null +++ b/gulliver/js/jquery/jquery-1.8.2.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
t
",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
","
"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/gulliver/js/jquery/jquery-ui-1.11.2.min.js b/gulliver/js/jquery/jquery-ui-1.11.2.min.js new file mode 100644 index 000000000..441a57980 --- /dev/null +++ b/gulliver/js/jquery/jquery-ui-1.11.2.min.js @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.11.2 - 2014-12-04 +* http://jqueryui.com +* Includes: core.js, widget.js, mouse.js, draggable.js, resizable.js +* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ + +(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return"area"===r?(n=t.parentNode,a=n.name,t.href&&a&&"map"===n.nodeName.toLowerCase()?(o=e("img[usemap='#"+a+"']")[0],!!o&&i(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+"px")})},e.fn["outer"+i]=function(t,n){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var s=0,n=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,a=n.call(arguments,1),o=0,r=a.length;r>o;o++)for(i in a[o])s=a[o][i],a[o].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(a){var o="string"==typeof a,r=n.call(arguments,1),h=this;return a=!o&&r.length?e.widget.extend.apply(null,[a].concat(r)):a,o?this.each(function(){var i,n=e.data(this,s);return"instance"===a?(h=n,!1):n?e.isFunction(n[a])&&"_"!==a.charAt(0)?(i=n[a].apply(n,r),i!==n&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+a+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var t=e.data(this,s);t?(t.option(a||{}),t._init&&t._init()):e.data(this,s,new i(a,this))}),h}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=s++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget;var a=!1;e(document).mouseup(function(){a=!1}),e.widget("ui.mouse",{version:"1.11.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!a){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var i=this,s=1===t.which,n="string"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return i._mouseMove(e)},this._mouseUpDelegate=function(e){return i._mouseUp(e)},this.document.bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),a=!0,!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button)return this._mouseUp(t);if(!t.which)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),a=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),e.widget("ui.draggable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),"handle"===e&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var i=this.options;return this._blurActiveElement(t),this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=e(this);return e("
").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var i=this.document[0];if(this.handleElement.is(t.target))try{i.activeElement&&"body"!==i.activeElement.nodeName.toLowerCase()&&e(i.activeElement).blur()}catch(s){}},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===e(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._normalizeRightBottom(),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(e){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:e.pageX-this.offset.left,top:e.pageY-this.offset.top}},_mouseDrag:function(t,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this.handleElement.addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.handleElement.removeClass("ui-draggable-handle")},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper),n=s?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options,a=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,e(a).width()-this.helperProportions.width-this.margins.left,(e(a).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(e,t){t||(t=this.position);var i="absolute"===e?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:t.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(e,t){var i,s,n,a,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.lefti[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a),"y"===o.axis&&(h=this.originalPageX),"x"===o.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i,s){var n=e.extend({},i,{item:s.element});s.sortables=[],e(s.options.connectToSortable).each(function(){var i=e(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",t,n))})},stop:function(t,i,s){var n=e.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,e.each(s.sortables,function(){var e=this;e.isOver?(e.isOver=0,s.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,n))})},drag:function(t,i,s){e.each(s.sortables,function(){var n=!1,a=this;a.positionAbs=s.positionAbs,a.helperProportions=s.helperProportions,a.offset.click=s.offset.click,a._intersectsWith(a.containerCache)&&(n=!0,e.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==a&&this._intersectsWith(this.containerCache)&&e.contains(a.element[0],this.element[0])&&(n=!1),n})),n?(a.isOver||(a.isOver=1,a.currentItem=i.helper.appendTo(a.element).data("ui-sortable-item",!0),a.options._helper=a.options.helper,a.options.helper=function(){return i.helper[0]},t.target=a.currentItem[0],a._mouseCapture(t,!0),a._mouseStart(t,!0,!0),a.offset.click.top=s.offset.click.top,a.offset.click.left=s.offset.click.left,a.offset.parent.left-=s.offset.parent.left-a.offset.parent.left,a.offset.parent.top-=s.offset.parent.top-a.offset.parent.top,s._trigger("toSortable",t),s.dropped=a.element,e.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,a.fromOutside=s),a.currentItem&&(a._mouseDrag(t),i.position=a.position)):a.isOver&&(a.isOver=0,a.cancelHelperRemoval=!0,a.options._revert=a.options.revert,a.options.revert=!1,a._trigger("out",t,a._uiHash(a)),a._mouseStop(t,!0),a.options.revert=a.options._revert,a.options.helper=a.options._helper,a.placeholder&&a.placeholder.remove(),s._refreshOffsets(t),i.position=s._generatePosition(t,!0),s._trigger("fromSortable",t),s.dropped=!1,e.each(s.sortables,function(){this.refreshPositions()}))})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,i,s){var n=e("body"),a=s.options;n.css("cursor")&&(a._cursor=n.css("cursor")),n.css("cursor",a.cursor)},stop:function(t,i,s){var n=s.options;n._cursor&&e("body").css("cursor",n._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("opacity")&&(a._opacity=n.css("opacity")),n.css("opacity",a.opacity)},stop:function(t,i,s){var n=s.options;n._opacity&&e(i.helper).css("opacity",n._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(e,t,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,i,s){var n=s.options,a=!1,o=s.scrollParentNotHidden[0],r=s.document[0];o!==r&&"HTML"!==o.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+o.offsetHeight-t.pageY=0;c--)h=s.snapElements[c].left-s.margins.left,l=h+s.snapElements[c].width,u=s.snapElements[c].top-s.margins.top,d=u+s.snapElements[c].height,h-m>v||g>l+m||u-m>b||y>d+m||!e.contains(s.snapElements[c].item.ownerDocument,s.snapElements[c].item)?(s.snapElements[c].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(n=m>=Math.abs(u-b),a=m>=Math.abs(d-y),o=m>=Math.abs(h-v),r=m>=Math.abs(l-g),n&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||a||o||r,"outer"!==f.snapMode&&(n=m>=Math.abs(u-y),a=m>=Math.abs(d-b),o=m>=Math.abs(h-g),r=m>=Math.abs(l-v),n&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d-s.helperProportions.height,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[c].snapping&&(n||a||o||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=n||a||o||r||p)}}),e.ui.plugin.add("draggable","stack",{start:function(t,i,s){var n,a=s.options,o=e.makeArray(e(a.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});o.length&&(n=parseInt(e(o[0]).css("zIndex"),10)||0,e(o).each(function(t){e(this).css("zIndex",n+t)}),this.css("zIndex",n+o.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("zIndex")&&(a._zIndex=n.css("zIndex")),n.css("zIndex",a.zIndex)},stop:function(t,i,s){var n=s.options;n._zIndex&&e(i.helper).css("zIndex",n._zIndex)}}),e.ui.draggable,e.widget("ui.resizable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(e){return parseInt(e,10)||0 +},_isNumber:function(e){return!isNaN(parseInt(e,10))},_hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return t[s]>0?!0:(t[s]=1,n=t[s]>0,t[s]=0,n)},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=this.element.children(this.handles[i]).first().show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var i,s,n,a=this.options,o=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),a.containment&&(i+=e(a.containment).scrollLeft()||0,s+=e(a.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:o.width(),height:o.height()},this.originalSize=this._helper?{width:o.outerWidth(),height:o.outerHeight()}:{width:o.width(),height:o.height()},this.sizeDiff={width:o.outerWidth()-o.width(),height:o.outerHeight()-o.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof a.aspectRatio?a.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===n?this.axis+"-resize":n),o.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var i,s,n=this.originalMousePosition,a=this.axis,o=t.pageX-n.left||0,r=t.pageY-n.top||0,h=this._change[a];return this._updatePrevProperties(),h?(i=h.apply(this,[t,o,r]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var e={};return this.position.top!==this.prevPosition.top&&(e.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(e.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(e.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(e.height=this.size.height+"px"),this.helper.css(e),e},_updateVirtualBoundaries:function(e){var t,i,s,n,a,o=this.options;a={minWidth:this._isNumber(o.minWidth)?o.minWidth:0,maxWidth:this._isNumber(o.maxWidth)?o.maxWidth:1/0,minHeight:this._isNumber(o.minHeight)?o.minHeight:0,maxHeight:this._isNumber(o.maxHeight)?o.maxHeight:1/0},(this._aspectRatio||e)&&(t=a.minHeight*this.aspectRatio,s=a.minWidth/this.aspectRatio,i=a.maxHeight*this.aspectRatio,n=a.maxWidth/this.aspectRatio,t>a.minWidth&&(a.minWidth=t),s>a.minHeight&&(a.minHeight=s),a.maxWidth>i&&(a.maxWidth=i),a.maxHeight>n&&(a.maxHeight=n)),this._vBoundaries=a},_updateCache:function(e){this.offset=this.helper.offset(),this._isNumber(e.left)&&(this.position.left=e.left),this._isNumber(e.top)&&(this.position.top=e.top),this._isNumber(e.height)&&(this.size.height=e.height),this._isNumber(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,i=this.size,s=this.axis;return this._isNumber(e.height)?e.width=e.height*this.aspectRatio:this._isNumber(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===s&&(e.left=t.left+(i.width-e.width),e.top=null),"nw"===s&&(e.top=t.top+(i.height-e.height),e.left=t.left+(i.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,i=this.axis,s=this._isNumber(e.width)&&t.maxWidth&&t.maxWidthe.width,o=this._isNumber(e.height)&&t.minHeight&&t.minHeight>e.height,r=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,l=/sw|nw|w/.test(i),u=/nw|ne|n/.test(i);return a&&(e.width=t.minWidth),o&&(e.height=t.minHeight),s&&(e.width=t.maxWidth),n&&(e.height=t.maxHeight),a&&l&&(e.left=r-t.minWidth),s&&l&&(e.left=r-t.maxWidth),o&&u&&(e.top=h-t.minHeight),n&&u&&(e.top=h-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_getPaddingPlusBorderDimensions:function(e){for(var t=0,i=[],s=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],n=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];4>t;t++)i[t]=parseInt(s[t],10)||0,i[t]+=parseInt(n[t],10)||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var e,t=0,i=this.helper||this.element;this._proportionallyResizeElements.length>t;t++)e=this._proportionallyResizeElements[t],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(e)),e.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,i,s,n,a,o,r,h=e(this).resizable("instance"),l=h.options,u=h.element,d=l.containment,c=d instanceof e?d.get(0):/parent/.test(d)?u.parent().get(0):d;c&&(h.containerElement=e(c),/document/.test(d)||d===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(c),i=[],e(["Top","Right","Left","Bottom"]).each(function(e,s){i[e]=h._num(t.css("padding"+s))}),h.containerOffset=t.offset(),h.containerPosition=t.position(),h.containerSize={height:t.innerHeight()-i[3],width:t.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,a=h.containerSize.width,o=h._hasScroll(c,"left")?c.scrollWidth:a,r=h._hasScroll(c)?c.scrollHeight:n,h.parentData={element:c,left:s.left,top:s.top,width:o,height:r}))},resize:function(t){var i,s,n,a,o=e(this).resizable("instance"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,d={top:0,left:0},c=o.containerElement,p=!0;c[0]!==document&&/static/.test(c.css("position"))&&(d=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-d.left),u&&(o.size.height=o.size.width/o.aspectRatio,p=!1),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio,p=!1),o.position.top=o._helper?h.top:0),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a?(o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top):(o.offset.left=o.element.offset().left,o.offset.top=o.element.offset().top),i=Math.abs(o.sizeDiff.width+(o._helper?o.offset.left-d.left:o.offset.left-h.left)),s=Math.abs(o.sizeDiff.height+(o._helper?o.offset.top-d.top:o.offset.top-h.top)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio,p=!1)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio,p=!1)),p||(o.position.left=o.prevPosition.left,o.position.top=o.prevPosition.top,o.size.width=o.prevSize.width,o.size.height=o.prevSize.height)},stop:function(){var t=e(this).resizable("instance"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).resizable("instance"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t,i=e(this).resizable("instance"),s=i.options,n=i.size,a=i.originalSize,o=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,u=h[1]||1,d=Math.round((n.width-a.width)/l)*l,c=Math.round((n.height-a.height)/u)*u,p=a.width+d,f=a.height+c,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,v=s.minWidth&&s.minWidth>p,y=s.minHeight&&s.minHeight>f;s.grid=h,v&&(p+=l),y&&(f+=u),m&&(p-=l),g&&(f-=u),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=o.top-c):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=o.left-d):((0>=f-u||0>=p-l)&&(t=i._getPaddingPlusBorderDimensions(this)),f-u>0?(i.size.height=f,i.position.top=o.top-c):(f=u-t.height,i.size.height=f,i.position.top=o.top+a.height-f),p-l>0?(i.size.width=p,i.position.left=o.left-d):(p=u-t.height,i.size.width=p,i.position.left=o.left+a.width-p))}}),e.ui.resizable}); \ No newline at end of file diff --git a/gulliver/js/pmchart/pmCharts.js b/gulliver/js/pmchart/pmCharts.js new file mode 100644 index 000000000..b9aa168ef --- /dev/null +++ b/gulliver/js/pmchart/pmCharts.js @@ -0,0 +1,2559 @@ +function drawAxisX(data, canvas, scale, parameter){ + if (!parameter.graph.axisX.showAxis) return; + //graph Dimensions inside the container + var graphDim = new GraphDim(parameter); + var xAxis = d3.svg.axis().scale(scale).orient('bottom').tickSize(parameter.graph.axisX.ticks); + + var x_axis = canvas.append('g') + .attr('class', 'axis') + .attr('transform','translate(0,' + graphDim.bottom + ')') + .call(xAxis) + .selectAll('text') + .style('text-anchor','end') + .attr('class', 'x-ticks-label') + .attr('transform','rotate(-45)'); + + + if (parameter.graph.axisX.showLabel) { + var labelPosX = graphDim.left + graphDim.width/2; + var labelPosY = graphDim.bottom + 55 + canvas.append("text") + .attr("transform", "translate(" + labelPosX + " ," + labelPosY + ")") + .attr('class','axis-label') + .style("text-anchor", "middle") + .text(parameter.graph.axisX.label); + } +} + +function drawAxisY(data, canvas, scale, parameter){ + if (!parameter.graph.axisY.showAxis) return; + var graphDim = new GraphDim(parameter); + var yAxis = d3.svg.axis().scale(scale).orient('left').ticks(parameter.graph.axisY.ticks); + var y_axis = canvas.append('g') + .attr('class','axis') + .attr('transform','translate(' + graphDim.top + ',0)') + .call(yAxis) + .selectAll('text') + .attr('class', 'y-ticks-label'); + + + if (parameter.graph.axisY.showLabel) { + canvas.append("text") + .attr('class','axis-label') + .attr("transform", "rotate(-90)") + .attr("y", 0) + .attr("x", -(graphDim.left + graphDim.height/2)) + .attr("dy", "1.5em") + .style("text-anchor", "end") + .text(parameter.graph.axisY.label); + } +} + + +var BarChart = function (data, params, previousDataPoint, breadcrumbs) { + this.originalData = data; + this.previousDataPoint = previousDataPoint; + this.params = params; + this.$container = $('#' + this.params.canvas.containerId); + //Breadcrumb stack: + this.breadCrumbStack = (breadcrumbs == null ) ? [] : breadcrumbs; + pushToStack(previousDataPoint, this); +}; + +BarChart.prototype.drawChart = function() { + var $container = $('#' + this.params.canvas.containerId); // canvas[0] to convert d3 to jquery object + $container.empty(); + $('.tooltipdiv').remove(); + stretchCanvas(null, this.$container, this.params); + this.canvas = createCanvas(this.params.canvas.containerId, this.params.canvas); + this.drawBars(this.originalData, this.canvas, this.params); + refreshBreadCrumbs(this); +}; + +BarChart.prototype.addBarTransition = function (bars, scaleX, scaleY) { + + /************* IN TRANSITION ****************/ + bars.attr("stroke-width", 4) + .transition() + .duration(300) + .attr("width", scaleX.rangeBand()) + .attr("y", function (d) { return scaleY(d.value) }); + + /*************** EXIT TRANSITION *****************/ + bars.exit() + .transition() + .duration(300) + .ease("exp") + .attr("width", 0) + .remove(); +} + +BarChart.prototype.drawBars = function(data, canvas, param) { + if (data == null || data.length == 0) { + this.$container.html( "
No data to draw ...
" ); + } + var parameter = createDefaultParamsForGraph(param); + //graph part of the parameters passed to this object + var graphParam = createDefaultParamsForLineChart(param.graph); + parameter.graph = graphParam; + + //graph Dimensions inside the container + var graphDim = new GraphDim(param); + + /*var totalPaddingTop = DEFAULT_PADDING + parameter.graph.paddingTop; + var h = parameter.canvas.height - totalPaddingTop - DEFAULT_PADDING; + var w = parameter.canvas.width - 2 * DEFAULT_PADDING; + var chartRight = w + DEFAULT_PADDING; + var chartBottom = h + totalPaddingTop; +*/ + var tooltip = new ToolTip(); + //HACK: to avoid context change in closure we store object's reference(this) here. + // JavaScript things... + var currObj = this; + + var xScaleLabels = data.map(function(data){ + return data.datalabel; + }); + + var maxValue = d3.max(data,function(d){ return d.value*1.0; }); + + var xScale = d3.scale + .ordinal() + .domain(xScaleLabels) + .rangeRoundBands([graphDim.left,graphDim.right], 0.15); + + var yScale = d3.scale + .linear() + .domain( [0, maxValue] ) + .range([graphDim.bottom, graphDim.top]) + .nice(); + + var chart = canvas.append('g'); + + drawAxisX(data, chart, xScale, parameter); + drawAxisY(data, chart, yScale, parameter); + drawLinesX(data, chart, xScale, parameter); + drawLinesY(data, chart, yScale, parameter); + + var bars = chart.selectAll('rect').data(data); + if (parameter.graph.allowZoom) { addZoomToCanvas(chart); } + addGradient(chart, "gradientForBars") + + bars.enter() + .append('rect') + .attr({ + 'x': function(d,i) { + return xScale(d.datalabel); + }, + 'y': function(d) { + return (parameter.graph.allowTransition) ? 0 : yScale(d.value); + }, + 'width': (parameter.graph.allowTransition) ? 0: xScale.rangeBand(), + 'height': function(d) { + return graphDim.bottom - yScale(d.value); + }, + 'fill': 'url(#gradientForBars)' + }) + .attr("clip-path", "url(#rectClip)") + .on("mouseover", function(d,i) { + d3.select(this) + .attr('fill', currObj.params.graph.colorPalette[i%currObj.params.graph.colorPalette.length]); + + tooltip.show(function () { + return {value: d.value, datalabel: d.datalabel} + }); + }) + .on('mouseout',function(d){ + d3.select(this) + .attr('fill','url(#gradientForBars)'); + tooltip.hide(); + }); + + + if (parameter.graph.allowTransition) {this.addBarTransition(bars, xScale, yScale);} + + + if (parameter.graph.useShadows){ + addShadow(canvas, "110%", 2); + chart.selectAll('rect') + .attr("filter", "url(#drop-shadow)"); + } + + + + if (this.params.graph.allowDrillDown) { + this.addOnClick(data, canvas); + if (this.breadCrumbStack.length > 0) { + var clip = chart.append("defs") + .append("svg:clipPath") + .attr("id", "clip") + .append("svg:rect") + .attr("id", "clip-rect") + .attr("x", "0") + .attr("y", "0") + .attr("width", 50) + .attr("height", 50) + .transition() + .duration(2000) + .attr("width", 500) + .attr("height", 500); + d3.select("svg g").attr('clip-path', 'url(#clip)'); + } + } + +} + +//function used to implement the drill-down +BarChart.prototype.addOnClick = function (arrayData, canvas) { + //HACK: to avoid context change in closue we store object's reference(this) here. + // JavaScript things... + var currObj = this; + canvas.selectAll("rect") + .data(arrayData) + .on("click", function (pointData) { + if (pointData.callBack != null && pointData.callBack.length != '') { + var $container = $(canvas[0]).parent(); + $container.empty(); + $('.tooltipdiv').remove(); + var funCallBack = eval(pointData.callBack); + funCallBack(pointData, currObj); + //pushToStack(pointData, currObj); + } + }); +}; + + + +var DEFAULT_PADDING = 50; + +function defaultAxis(axisParam) { + var retval = {}; + addValueForProperty(retval, axisParam, 'showLabel', true); + addValueForProperty(retval, axisParam, 'showAxis', true); + addValueForProperty(retval, axisParam, 'label', 'X'); + addValueForProperty(retval, axisParam, 'ticks', 10); + return retval; +} + +function addValueForProperty(targetObject, baseObject, property, defaultValue) { + if (property in baseObject) { + targetObject[property] = baseObject[property]; + } + else { + targetObject[property] = defaultValue; + } + +} + +function createDefaultParamsForGraph(param) { + if (param.canvas == null) {throw new Error('You need specify canvas configuration parameters.');} + if (param.graph == null) {throw new Error('You need specify graph configuration parameters.');} + if (param.canvas.width == null) {throw new Error('No canvas width specified.');} + if (param.canvas.height == null) {throw new Error('No canvas height specified.');} + + var retval = { + canvas: { + width: ("width" in param.canvas) ? param.canvas.width : 100 , + height: ("height" in param.canvas) ? param.canvas.height : 100 , + exportTo: ("exportTo" in param.canvas) ? param.canvas.exportTo : [], + stretch: ("stretch" in param.canvas) ? param.canvas.stretch : true + }, + graph: { + allowTransition: ("allowTransition" in param.graph) ? param.graph.allowTransition : false, + allowZoom: ("allowZoom" in param.graph) ? param.graph.allowZoom : false, + useShadows: ("useShadows" in param.graph) ? param.graph.useShadows : false, + showTip: ("showTip" in param.graph) ? param.graph.showTip : false, + paddingTop: ("paddingTop" in param.graph) ? param.graph.paddingTop : 50, + axisX: ("axisX" in param.graph) ? defaultAxis(param.graph.axisX) : defaultAxis({}), + axisY: ("axisY" in param.graph) ? defaultAxis(param.graph.axisY) : defaultAxis({}), + colorPalette: ("colorPalette" in param.graph) ? param.graph.colorPalette : ["#62C1A3", "#FB906B", "#8DA1CB", "#E88AC2", "#E4C18F", "#B3B3B3", "#3180BA", "#50B14D", "#9A51A4", "#F87709", "#A35920","#A6D954", "#FED92F", "#ED2617"] + }, + linesx: true, + linesy: true + }; + return retval; + /*axisX: ("axisX" in param.graph) ? param.graph.axisX : { showAxis: true, label: "X", showLabel: true, ticks: 5 }, + axisY: ("axisY" in param.graph) ? param.graph.axisY : { showAxis: true, label: "Y", showLable: true, ticks: 5 },*/ +} +function createDefaultParamsForGraphRign(param) { + + if (param.canvas == null) {throw new Error('You need specify canvas configuration parameters.');} + if (param.graph == null) {throw new Error('You need specify graph configuration parameters.');} + if (param.canvas.width == null) {throw new Error('No canvas width specified.');} + if (param.canvas.height == null) {throw new Error('No canvas height specified.');} + + var retval = { + canvas: { + width: ("width" in param.canvas) ? param.canvas.width : 200 , + height: ("width" in param.canvas) ? param.canvas.height : 200 , + exportTo: ("exportTo" in param.canvas) ? param.canvas.exportTo : [], + stretch: ("stretch" in param.canvas) ? param.canvas.stretch : true + }, + graph: { + ringColor :("ringColor" in param.graph) ? param.graph.ringColor : '#74cc84', + labelColor :("labelColor" in param.graph) ? param.graph.labelColor : 'red', + diameter : ("diameter" in param.graph) ? param.graph.diameter : 200, + gapWidth :("gapWidth" in param.graph) ? param.graph.gapWidth :50, + useShadows: ("useShadows" in param.graph) ? param.graph.useShadows : false, + allowTransition: ("allowTransition" in param.graph) ? param.graph.allowTransition : false, + allowZoom: ("allowZoom" in param.graph) ? param.graph.allowZoom : false + } + }; + return retval; +} +function createDefaultParamsForGraphVelocimeter(param) { + + if (param.canvas == null) {throw new Error('You need specify canvas configuration parameters.');} + if (param.graph == null) {throw new Error('You need specify graph configuration parameters.');} + if (param.canvas.width == null) {throw new Error('No canvas width specified.');} + if (param.canvas.height == null) {throw new Error('No canvas height specified.');} + + var retval = { + canvas: { + width: ("width" in param.canvas) ? param.canvas.width : 700 , + height: ("width" in param.canvas) ? param.canvas.height : 200 , + exportTo: ("exportTo" in param.canvas) ? param.canvas.exportTo : [], + stretch: ("stretch" in param.canvas) ? param.canvas.stretch : true + }, + graph: { + useShadows: ("useShadows" in param.graph) ? param.graph.useShadows : false, + allowZoom: ("allowZoom" in param.graph) ? param.graph.allowZoom : false + } + }; + return retval; +} +function createDefaultParamsForGraphPie(param) { + if (param.canvas == null) {throw new Error('You need specify canvas configuration parameters.');} + if (param.graph == null) {throw new Error('You need specify graph configuration parameters.');} + if (param.canvas.width == null) {throw new Error('No canvas width specified.');} + if (param.canvas.height == null) {throw new Error('No canvas height specified.');} + + //if (param.graph.axisX == null) {param.graph.axisX = { showAxis: true, label: "X" };} + //if (param.graph.axisY == null) {param.graph.axisX = { showAxis: true, label: "Y" };} + + + + var retval = { + canvas: { + width: ("width" in param.canvas) ? param.canvas.width : 100 , + height: ("height" in param.canvas) ? param.canvas.height : 100 , + exportTo: ("exportTo" in param.canvas) ? param.canvas.exportTo : [], + stretch: ("stretch" in param.canvas) ? param.canvas.stretch : true + }, + graph: { + allowTransition: ("allowTransition" in param.graph) ? param.graph.allowTransition : false, + //axisX: ("axisX" in param.graph) ? param.graph.axisX : false, + //axisY: ("axisY" in param.graph) ? param.graph.axisY : false, + allowDrillDown: ("allowDrillDown" in param.graph) ? param.graph.allowDrillDown : false, + allowZoom: ("allowZoom" in param.graph) ? param.graph.allowZoom : false, + useShadows: ("useShadows" in param.graph) ? param.graph.useShadows : false, + showTip: ("showTip" in param.graph) ? param.graph.showTip : false, + thickness: ("thickness" in param.graph) ? param.graph.thickness : 50, + showLabels: ("showLabels" in param.graph) ? param.graph.showLabels : false, + colorPalette: ("colorPalette" in param.graph) ? param.graph.colorPalette : ["#62C1A3", "#FB906B", "#8DA1CB", "#E88AC2", "#E4C18F", "#B3B3B3", "#3180BA", "#50B14D", "#9A51A4", "#F87709", "#A35920","#A6D954", "#FED92F", "#ED2617"] + } + //linesx: true, + //linesy: true + }; + return retval; +} +function createDefaultParamsForLineChart(param) { + var graphParam = { + axisX: ("axisX" in param) ? defaultAxis(param.axisX) : defaultAxis({}), + axisY: ("axisY" in param) ? defaultAxis(param.axisY) : defaultAxis({}) + }; + addValueForProperty(graphParam, param, 'allowTransition', false); + addValueForProperty(graphParam, param, 'allowZoom', false); + addValueForProperty(graphParam, param, 'useShadows', false); + addValueForProperty(graphParam, param, 'showTip', false); + addValueForProperty(graphParam, param, 'paddingTop', 0); + addValueForProperty(graphParam, param, 'area', { visible: false, css: "area"}); + addValueForProperty(graphParam, param, 'marker', { visible: true, ratio: 5, css: "default"}); + addValueForProperty(graphParam, param, 'line', { visible: true, css: "line1"}); + addValueForProperty(graphParam, param, 'gridLinesX', true); + addValueForProperty(graphParam, param, 'gridLinesY', true); + addValueForProperty(graphParam, param, 'showErrorBars', false); + return graphParam; +} + +function stretchCanvas(canvas, $container, params) { + if (params.canvas.stretch) { + if ($container.width() == null || $container.height() == null) { + throw new Error('stretchCanvas: The container ' + $container.attr('id') + ' must have a width and height assigned.') + } + var widthToUse = ($container.width() == null || $container.width() == 0) ? params.canvas.width : $container.width(); + var heightToUse = ($container.height() == null || $container.height() == 0) ? params.canvas.height : $container.height(); + + + + //for ring + var diameterToUse = d3.min([widthToUse, heightToUse], + function (d) {return d;} + ); + params.canvas.width = widthToUse; + params.canvas.height = heightToUse; + params.graph.diameter = diameterToUse; + } + + //TODO a better way is to stretch using SVG native functions. The following code does not work correctly + /*canvas.attr('width', '100%') + .attr('height', '98%') + .attr("viewBox", "0 0 " + .$container.width()+ " " + $containr.height()) + .attr("preserveAspectRatio", "xMidYMid meet") + .attr("pointer-events", "all"); + return canvas;*/ +} + +function redrawChart(chart) { + chart.attr("transform", + "translate(" + d3.event.translate + ")" + + " scale(" + d3.event.scale + ")"); +} + +function createCanvas (selectorId, param) { + d3.select('#'+selectorId).select('svg').remove(); + var canvas = d3.select('#'+selectorId) + .append('svg') + .attr('width', param.width) + .attr('height', param.height); + return canvas; +} + +function addZoomToCanvas(canvas) { + /*canvas.call(d3.behavior.zoom().on("zoom", function () { + canvas.attr("transform", + "translate(" + d3.event.translate + ")" + + " scale(" + d3.event.scale + ")"); + }));*/ + var zoom = d3.behavior.zoom() + .scaleExtent([1, 3]) + .on("zoom", function(){ + canvas.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); + }); + canvas.call(zoom); + +} + +function addExportOptions(container, exportOptions) { + var arr = []; + $(exportOptions).each (function() { + arr.push({val:this.toLowerCase(), text: this}) + }); + + /*var arr = [ + {val : 'pdf', text: 'PDF'}, + {val : 'png', text: 'PNG'}, + {val : 'svg', text: 'SVG'} + ];*/ + + var sel = $('', { + 'name': 'output_format', + 'value': exportType, + 'type': 'hidden' + })); + + newForm.append(jQuery('', { + 'name': 'data', + 'value': svgSerialized, + 'type': 'hidden' + })); + + newForm.get(0).submit();*/ + }); + container.append(sel); +} + +function addDefsSection(canvas) { + var defs = canvas.select('defs'); + if (defs.empty()) { + defs = canvas.append('defs'); + } + return defs; +} + +function addGradient(canvas, gradientId) { + + defs = addDefsSection (canvas); + + var gradient = defs.append("linearGradient") + .attr("id", gradientId) + .attr("y1", 10) + .attr("y2", 800) + .attr("x1", "0") + .attr("x2", "0") + .attr("gradientUnits", "userSpaceOnUse"); + + gradient.append("stop") + .attr("offset", "0") + .attr("stop-color", "#99d5cf") + + gradient.append("stop") + .attr("offset", "0.5") + .attr("stop-color", "#009688") +} + +function linesX(data,selector,parameter){ + + var width = parameter.width; + var svg = d3.select('#'+selector+' svg'); + + var arra = [], + lens; + for (key in data) { + arra.push(key); + } + lens = arra.length; + var barLabelsx = data.map(function(data){ + return data.datalabel; + }); + + var sx = d3.scale.ordinal().domain(barLabelsx).rangePoints([50, width-50]); + + function make_x_axis() { + return d3.svg.axis() + .scale(sx) + .orient("bottom") + .ticks(lens) + } + + var group3 = svg.append("g"); + group3.append("g") + .attr("class", "grid") + .attr("transform", "translate(0," + 240 + ")") + .call(make_x_axis() + .tickSize(-220, 0, 0) + .tickFormat("") + ); +} + +function linesY(data, selector, parameter){ + +} +/* +function addToolTip(canvas) { + var div = d3.select("body") + .append("div") + .attr("class", "tooltipdiv") + .style("opacity", 0) + .style("width","auto") + .style("height","auto"); + return div; +}*/ + + +/*function addToolTip(canvas, template) { + if (template === undefined) { + var template = "Value: %value%
Datalabel: %datalabel%"; + } + var tip = d3.tip() + .attr('class', 'd3-tip') + .offset([-10, 0]) + .html(function(d) { + var replacements = {'%value%' : d.value, '%datalabel%' : d.datalabel}; + return template.replace(/%\w+%/g, function(all) { return replacements[all] || all; }); + }); + canvas.call(tip); + return tip; +}*/ + +function addToolTipPie(canvas) { + + var tip = d3.tip() + .attr('class', 'd3-tip') + .offset([-10, 0]) + .html(function(d) { + return "Value: "+d.data.value+"
Data Label: "+d.data.label+""; + }); + canvas.call(tip); + return tip; +} + +function addToolTipPie2D(canvas, stretch) { + + var tip = d3.tip() + .attr('class', 'd3-tip') + .offset(function () { + if(stretch) { return [240,0] } + else { return [0,0] } + }) + .html(function(d,i) { + return "Value: "+d.value+"
Data Label: "+d.data.cat+""; + }); + canvas.call(tip); + return tip; +} + + +function addShadow(canvas, shadowHeightPercent, shadowWidth) +{ + var defs = addDefsSection (canvas); + + var filter = defs.append("filter") + .attr("id", "drop-shadow") + .attr("height", shadowHeightPercent); + + // SourceAlpha refers to opacity of graphic that this filter will be applied to + // convolve that with a Gaussian with standard deviation 3 and store result + // in blur + filter.append("feGaussianBlur") + .attr("in", "SourceAlpha") + .attr("stdDeviation", shadowWidth) + .attr("result", "blur"); + + // translate output of Gaussian blur to the right and downwards with 2px + // store result in offsetBlur + filter.append("feOffset") + .attr("in", "blur") + .attr("dx", 1.5) + .attr("dy", 2) + .attr("result", "offsetBlur"); + + // overlay original SourceGraphic over translated blurred opacity by using + // feMerge filter. Order of specifying inputs is important! + var feMerge = filter.append("feMerge"); + + feMerge.append("feMergeNode") + .attr("in", "offsetBlur") + feMerge.append("feMergeNode") + .attr("in", "SourceGraphic"); +} + + +function drawLinesX(data, chart, sx, parameter){ + if (!parameter.graph.gridLinesX) return; + var DEFAULT_PADDING = 50; + var totalPaddingTop = DEFAULT_PADDING + parameter.graph.paddingTop; + var height = parameter.canvas.height - totalPaddingTop - DEFAULT_PADDING; + var width = parameter.canvas.width - 2 * DEFAULT_PADDING; + var chartRight = width + DEFAULT_PADDING; + var chartBottom = height + totalPaddingTop; + + var arra = [], + lens; + for (key in data) { + arra.push(key); + } + lens = arra.length; + var barLabelsx = data.map(function(data){ + return data.datalabel; + }); + + function make_x_axis() { + return d3.svg.axis() + .scale(sx) + .orient("bottom") + .ticks(parameter.graph.axisX.ticks) + } + + var group3 = chart.append("g"); + group3.append("g") + .attr("class", "grid") + .attr("transform", "translate(0,"+totalPaddingTop+")") + .call(make_x_axis() + .tickSize(height, 0, 0) + .tickFormat("") + ); +} + +function drawLinesY(data, chart, sy, parameter){ + if (!parameter.graph.gridLinesY) return; + var DEFAULT_PADDING = 50; + var totalPaddingTop = DEFAULT_PADDING + parameter.graph.paddingTop; + var height = parameter.canvas.height - totalPaddingTop - DEFAULT_PADDING; + var width = parameter.canvas.width - 2 * DEFAULT_PADDING; + var chartRight = width + DEFAULT_PADDING; + var chartBottom = height + totalPaddingTop; + + var maxValue = d3.max(data,function(d){ return d.value*1.0; }); + /*var sy = d3.scale.linear().domain( [0,maxValue] ).range( [chartBottom,15] ).nice();*/ + function make_y_axis() { + return d3.svg.axis() + .scale(sy) + .orient("left") + /*.attr('transform',function(d, i){ + return "translate(0," + (i * 25 + 12) + ")" + })*/ + .ticks(parameter.graph.axisY.ticks) + } + + var group3 = chart.append("g"); + group3.append("g") + .attr("class", "grid") + .attr("transform", "translate(" + DEFAULT_PADDING + ",0)") + .call(make_y_axis() + .tickSize(-width, 0, 0) + .tickFormat("") + ); +} + +function pushToStack(selectedDataPoint, graphObject) { + var objToAdd = { + previousDataPoint : selectedDataPoint, + graph : graphObject + } + graphObject.breadCrumbStack.push(objToAdd); +} + +function refreshBreadCrumbs(graphObject) { + //if there is just one element do nothing. + if (graphObject.breadCrumbStack.length <= 1 ) { + return; + } + + graphObject.$container.children('.graph-breadcrumb-div').remove(); + graphObject.$container.append('
'); + var breadCrumbsDiv = graphObject.$container.children('.graph-breadcrumb-div').first(); + + for (var i = 0; i < graphObject.breadCrumbStack.length; i++) { + var item = graphObject.breadCrumbStack[i]; + var $newLink = $(document.createElement("a")); + $newLink.attr("class", "graph-breadcrumb-link"); + $newLink.text((item.previousDataPoint == null) + ? "init" + : item.previousDataPoint.datalabel); + $newLink.attr('href','#'); + $newLink.attr('data-index', i); + + $newLink.click(function() { + var index = $(this).data('index'); + for (var i = index; i < graphObject.breadCrumbStack.length; i++) { + graphObject.breadCrumbStack.pop(); + } + //getting array's last element + var element = graphObject.breadCrumbStack.slice(-1)[0]; + element.graph.drawChart(); + }); + $newLink.appendTo(breadCrumbsDiv); + if (i < graphObject.breadCrumbStack.length -1) { + breadCrumbsDiv.append(" >> "); + } + } +} + +//graph dimensions +var GraphDim = function (params) { + var DEFAULT_PADDING = 50; + this.top = DEFAULT_PADDING; + this.left = DEFAULT_PADDING; + this.height = params.canvas.height - 2 * DEFAULT_PADDING - 20; + this.width = params.canvas.width - 2 * DEFAULT_PADDING; + this.bottom = this.height + this.top; + this.right = this.width + this.left; +}; + + + +var LineChart = function (data, params, previousDataPoint, breadcrumbs) { + this.originalData = data; + this.previousDataPoint = previousDataPoint; + this.params = params; + this.$container = $('#' + this.params.canvas.containerId); + //Breadcrumb stack: + this.breadCrumbStack = (breadcrumbs == null ) ? [] : breadcrumbs; + pushToStack(previousDataPoint, this); +}; + +LineChart.prototype.drawChart = function() { + var $container = $('#' + this.params.canvas.containerId); // canvas[0] to convert d3 to jquery object + $container.empty(); + $('.tooltipdiv').remove(); + + //TODO better if this is done inside the building function(drawLines) + stretchCanvas(null, this.$container, this.params); + + this.canvas = createCanvas(this.params.canvas.containerId, this.params.canvas); + this.drawLines(this.originalData, this.canvas, this.params); + refreshBreadCrumbs(this); +}; + +LineChart.prototype.addTransitionToCircle = function(circle, ratio) { + circle.transition() + .duration(1000) + .attr({ + r : ratio + }); +}; + +LineChart.prototype.drawLines = function (data, canvas, param) { + if (data == null || data.length == 0) { + this.$container.html( "
No data to draw ...
" ); + } + + var parameter = createDefaultParamsForGraph(param); + //graph part of the parameters passed to this object + var graphParam = createDefaultParamsForLineChart(param.graph); + parameter.graph = graphParam; + + //graph Dimensions inside the container + var graphDim = new GraphDim(param); + + var tooltip = new ToolTip(); + //HACK: to avoid context change in closure we store object's reference(this) here. + // JavaScript things... + var currObj = this; + + var xScaleLabels = data.map(function(data){ + return data.datalabel; + }); + + var maxValue = d3.max(data,function(d){ return d.value*1.0; }); + + var xScale = d3.scale + .ordinal() + .domain(xScaleLabels) + .rangePoints([graphDim.left, graphDim.right], 0); + + var yScale = d3.scale + .linear() + .domain([0, maxValue]) + .range([graphDim.bottom, graphDim.top]).nice(); + + var chart = canvas.append("g"); + + drawAxisX(data, chart, xScale, parameter); + drawAxisY(data, chart, yScale, parameter); + drawLinesX(data, chart, xScale, parameter); + drawLinesY(data, chart, yScale, parameter); + + var area = d3.svg.area() + .x(function(d) { return xScale(d.datalabel); }) + .y0(graphDim.bottom) + .y1(function(d) { return yScale(d.value); }); + + var lineForValue = d3.svg.line() + .x(function(d) { return xScale(d.datalabel); }) + .y(function(d) { return yScale(d.value); }); + + + if (parameter.graph.allowZoom) { addZoomToCanvas(chart);} + + data.forEach(function(d) { + d.value = +d.value; + }); + + var data0; + + if (parameter.canvas.exportTo != null && parameter.canvas.exportTo.length > 0) { + addExportOptions($('#' + this.params.canvas.containerId), this.params.canvas.exportTo); + } + + if (parameter.graph.allowTransition) { + data0 = data.map(function (d) { return {datalabel : d.datalabel, value : 0}; }); + } + else { + data0 = data; + } + + // Add the valueline path. + chart.append("path") + .attr("d", lineForValue(data0)) + .attr("class", parameter.graph.line.css) + .transition() + .duration(3000) + .attr("d", lineForValue(data)); + + if (parameter.graph.area.visible) { + var pathArea = chart.append("path"); + + pathArea + .datum(data0) + .attr("class", parameter.graph.area.css) + .attr("d", area); + } + + chart.selectAll("circle") + .data(data0) + .enter() + .append("circle") + .attr("class", parameter.graph.marker.css) + .each(function(d){ + d3.select(this).attr({ + cx: xScale(d.datalabel), + cy: yScale(d.value), + r: parameter.graph.marker.ratio + }); + }); + + if (parameter.graph.showErrorBars) { + chart.selectAll(".errorBar") + .data (data0) + .enter() + .append("path") + .attr("class", "errorBar") + .each(function (d) { + var delta = d.dispersion / 2; + var xVal = xScale(d.datalabel); + var yVal0 = yScale(d.value - delta); + var yVal1 = yScale(d.value + delta); + d3.select(this) + .attr ("d", "M" + xVal + "," + yVal0 + + "L" + xVal + "," + yVal1); + + }); + + chart.selectAll(".errorBarLowerMark") + .data (data0) + .enter() + .append("path") + .attr("class", "errorBarLowerMark") + .each(function (d) { + var delta = d.dispersion / 2; + var xVal = xScale(d.datalabel); + var yVal0 = yScale(d.value - delta); + var yVal1 = yScale(d.value + delta); + d3.select(this) + .attr ("d", "M" + (xVal - 5) + "," + yVal0 + + "L" + (xVal + 5) + "," + yVal0) + }); + + chart.selectAll(".errorBarUpperMark") + .data (data0) + .enter() + .append("path") + .attr("class", "errorBarUpperMark") + .each(function (d) { + var delta = d.dispersion / 2; + var xVal = xScale(d.datalabel); + var yVal0 = yScale(d.value - delta); + var yVal1 = yScale(d.value + delta); + d3.select(this) + .attr ("d", "M" + (xVal - 5) + "," + yVal1 + + "L" + (xVal + 5) + "," + yVal1) + }); + + } + + if (parameter.graph.allowTransition) { + if (parameter.graph.area.visible) { + pathArea + .datum(data) + .transition() + .duration(3000) + .attr("d", area); + } + + chart.selectAll("circle") + .data(data) + .each(function(d){ + d3.select(this) + .transition() + .duration(3000) + .attr('class', parameter.graph.marker.css) + .attr({ + cx: xScale(d.datalabel), + cy: yScale(d.value) + }); + }); + } + + //colocamos este código después de la transición para asegurarnos + //que se usan los datos correctos. + if (parameter.graph.showTip) { + chart.selectAll('circle') + .data(data) + .on('mouseover', function (d) { + tooltip.show(function () { + if (parameter.graph.showErrorBars) + return {value: d.value + ' (sdv = ' + d.dispersion + ')', datalabel: d.datalabel} + else + return {value: d.value, datalabel: d.datalabel} + }); + currObj.addTransitionToCircle(d3.select(this), parameter.graph.marker.ratio); + }) + .on('mouseout', function () { + currObj.addTransitionToCircle(d3.select(this), parameter.graph.marker.ratio); + if(parameter.graph.showTip) { + tooltip.hide(); + } + }) + } + + if (this.params.graph.allowDrillDown) { + this.addOnClick(data, canvas); + if (this.breadCrumbStack.length > 0) { + var clip = chart.append("defs") + .append("svg:clipPath") + .attr("id", "clip") + .append("svg:rect") + .attr("id", "clip-rect") + .attr("x", "0") + .attr("y", "0") + .attr("width", 50) + .attr("height", 50) + .transition() + .duration(2000) + .attr("width", 500) + .attr("height", 500); + d3.select("svg g").attr('clip-path', 'url(#clip)'); + } + } +}; + +//function used to implement the drill-down +LineChart.prototype.addOnClick = function (arrayData, canvas) { + //HACK: to avoid context change in closue we store object's reference(this) here. + // JavaScript things... + var currObj = this; + canvas.selectAll("circle") + .data(arrayData) + .on("click", function (pointData) { + if (pointData.callBack != null && pointData.callBack.length != '') { + var $container = $(canvas[0]).parent(); + $container.empty(); + $('.d3-tip').remove(); + var funCallBack = eval(pointData.callBack); + funCallBack(pointData, currObj); + } + }); +}; + + +var PieChart = function (data, params, previousDataPoint, breadcrumbs) { + this.originalData = data; + this.previousDataPoint = previousDataPoint; + this.params = params; + this.$container = $('#' + this.params.canvas.containerId); + //Breadcrumb stack: + this.breadCrumbStack = (breadcrumbs == null ) ? [] : breadcrumbs; + pushToStack(previousDataPoint, this); +}; + +PieChart.prototype.drawChart = function () { + var $container = $('#' + this.params.canvas.containerId); // canvas[0] to convert d3 to jquery object + $container.empty(); + $('.tooltipdiv').remove(); + + //TODO better if this is done inside the building function(drawLines) + stretchCanvas(null, this.$container, this.params); + + this.canvas = createCanvas(this.params.canvas.containerId, this.params.canvas); + this.drawPie2D(this.originalData, this.canvas, this.params); + refreshBreadCrumbs(this); +}; + +PieChart.prototype.drawPie2D = function (dataset, canvas, param) { + if (dataset == null || dataset.length == 0) { + this.$container.html( "
No data to draw ...
" ); + } + + var parameter = createDefaultParamsForGraphPie(param); + var width = parameter.canvas.width, + height = parameter.canvas.height; + + var tooltip = new ToolTip(); + + if (parameter.graph.showLabels) { + height = height - 50; + width = width - 150; + } + + var margin = 50, + radius = Math.min(width - margin, height - margin) / 2, + // Pie layout will use the "val" property of each data object entry + pieChart = d3.layout.pie().sort(null).value(function (d) { + return d.value; + }), + arc = d3.svg.arc().outerRadius(radius); + var colors2 = parameter.graph.colorPalette; + + + // Synthetic data generation ------------------------------------------------ + var data = Data(dataset); + + function Data(data) { + return data.map(function (d, i) { + var newcolor; + if (i == parameter.graph.colorPalette.length) { + newcolor = "#000000"; + } else { + newcolor = colors2[i % parameter.graph.colorPalette.length]; + } + var children = []; + var color = colors2[i]; +/* children.push({ + datalabel: "datalabel" + ((i + 1) * 100 + i), + value: Math.random(), + color: d3.rgb(color).darker(1 / (i + 1)) + });*/ + return { + datalabel: (d.datalabel), + value: (d.value * 1), + //color: colors2[i%(parameter.graph.colorPalette.length-1)], + color: newcolor, + children: children, + callBack: d.callBack + }; + }); + } + + var totalValues = 0; + + + for (var i = 0; i < data.length; i++) { + totalValues = totalValues + data[i].value; + } + + + // -------------------------------------------------------------------------- + // SVG elements init + //var svg = d3.select("body").append("svg").attr("width", width).attr("height", height), + var chart = canvas.append('g'); + var svg = chart, + defs = svg.append("svg:defs"), + // Declare a main gradient with the dimensions for all gradient entries to refer + mainGrad = defs.append("svg:radialGradient") + .attr("gradientUnits", "userSpaceOnUse") + .attr("cx", 0).attr("cy", 0).attr("r", radius).attr("fx", 0).attr("fy", 0) + .attr("id", "master") + // The pie sectors container + arcGroup = svg.append("svg:g") + .attr("class", "arcGroup") + //.attr("filter", "url(#shadow)") + .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")"), + // Header text + header = svg.append("text").text("") + .attr("transform", "translate(10, 20)").attr("class", "header"); + + + if (parameter.graph.allowZoom) { + addZoomToCanvas(chart); + } + + + // Redraw the graph given a certain level of data + + function updateGraph(currObject, datalabel) { + var currData = data; + + // Simple header text + if (datalabel != undefined) { + currData = findChildenByCat(datalabel); + d3.select(".header").text(""); + } else { + d3.select(".header").text(""); + } + + // Create a gradient for each entry (each entry identified by its unique category) + var gradients = defs.selectAll(".gradient").data(currData, function (d) { + return d.datalabel; + }); + gradients.enter().append("svg:radialGradient") + .attr("id", function (d, i) { + return "gradient" + d.datalabel; + }) + .attr("class", "gradient") + .attr("xlink:href", "#master"); + + gradients.append("svg:stop").attr("offset", "0%").attr("stop-color", getColor); + gradients.append("svg:stop").attr("offset", "90%").attr("stop-color", getColor); + gradients.append("svg:stop").attr("offset", "100%").attr("stop-color", getDarkerColor); + + + // Create a sector for each entry in the enter selection + var paths = arcGroup.selectAll("path") + .data(pieChart(currData), function (d) { + return d.data.datalabel; + }); + + paths.enter().append("svg:path").attr("class", "sector"); + + + if (currObject.params.graph.allowDrillDown) { + currObject.addOnClick(data, paths, canvas); + if (currObject.breadCrumbStack.length > 0) { + var clip = chart.append("defs") + .append("svg:clipPath") + .attr("id", "clip") + .append("svg:rect") + .attr("id", "clip-rect") + .attr("x", "0") + .attr("y", "0") + .attr("width", 50) + .attr("height", 50) + .transition() + .duration(2000) + .attr("width", 500) + .attr("height", 500); + d3.select("svg g").attr('clip-path', 'url(#clip)'); + } + } + + // Each sector will refer to its gradient fill + paths.attr("fill", function (d, i) { + return "url(#gradient" + d.data.datalabel + ")"; + }) + .transition().duration(1000).attrTween("d", tweenIn).each("end", function () { + this._listenToEvents = true; + }); + + // Mouse interaction handling + /* + paths.on("click", function(d){ + if(this._listenToEvents){ + // Reset inmediatelly + d3.select(this).attr("transform", "translate(0,0)") + // Change level on click if no transition has started + paths.each(function(){ + this._listenToEvents = false; + }); + updateGraph(d.data.children? d.data.datalabel : undefined); + } + }) + */ + paths.on("mouseover", function (d) { + // Mouseover effect if no transition has started + if (this._listenToEvents) { + // Calculate angle bisector + var ang = d.startAngle + (d.endAngle - d.startAngle) / 2; + // Transformate to SVG space + ang = (ang - (Math.PI / 2)) * -1; + + // Calculate a 10% radius displacement + var x = Math.cos(ang) * radius * 0.1; + var y = Math.sin(ang) * radius * -0.1; + + d3.select(this).transition() + .duration(250).attr("transform", "translate(" + x + "," + y + ")"); + } + + if (parameter.graph.showTip) { + tooltip.show(function () { + return { + value: d.value, + datalabel: d.data.datalabel + } + }); + } + }) + .on("mouseout", function (d) { + // Mouseout effect if no transition has started + if (this._listenToEvents) { + d3.select(this).transition() + .duration(150).attr("transform", "translate(0,0)"); + } + if (parameter.graph.showTip) { + tooltip.hide(); + } + }); + + // Collapse sectors for the exit selection + paths.exit().transition() + .duration(1000) + .attrTween("d", tweenOut).remove(); + } + + // "Fold" pie sectors by tweening its current start/end angles + // into 2*PI + function tweenOut(data) { + data.startAngle = data.endAngle = (2 * Math.PI); + var interpolation = d3.interpolate(this._current, data); + this._current = interpolation(0); + return function (t) { + return arc(interpolation(t)); + }; + } + + + // "Unfold" pie sectors by tweening its start/end angles + // from 0 into their final calculated values + function tweenIn(data) { + var interpolation = d3.interpolate({ + startAngle: 0, + endAngle: 0 + }, data); + this._current = interpolation(0); + return function (t) { + return arc(interpolation(t)); + }; + } + + + // Helper function to extract color from data object + function getColor(data, index) { + return data.color; + } + + + // Helper function to extract a darker version of the color + function getDarkerColor(data, index) { + return d3.rgb(getColor(data, index)).darker(0.7); + } + + + function findChildenByCat(datalabel) { + for (i = -1; i++ < data.length - 1;) { + if (data[i].datalabel == datalabel) { + return data[i].children; + } + } + return data; + } + + function getPercent(d) { + + return (Math.round(100 * d / totalValues * 10) / 10 + '%'); + } + + // Start by updating graph at root level + updateGraph(this); + + if (parameter.graph.showLabels) { + var thickness = 119 * Math.log(parameter.canvas.height) - 645; + var group5 = chart.append("g") + .attr("class", "group5") + .attr("transform", "translate(0," + thickness + ")"); + for (var i = 0; i < data.length; i++) { + var newcolor; + if (i == parameter.graph.colorPalette.length) { + newcolor = "#000000"; + } else { + newcolor = colors2[i % parameter.graph.colorPalette.length]; + } + group5.append("circle") + .attr("r", 9) + .attr("fill", newcolor) + .attr("cx", width) + .attr("cy", (i * 25)); + } + + group5.selectAll("text") + .data(data) + .enter() + .append("text") + .attr("x", width + 30) + .text(function (d, i) { + return (d.datalabel + "-" + getPercent(d.value)) + }) + .attr("transform", function (d, i) { + return "translate(0," + (i * 25 + 5) + ")" + }); + } + +} + +//function used to implement the drill-down +PieChart.prototype.addOnClick = function (arrayData, paths, canvas) { + //HACK: to avoid context change in closue we store object's reference(this) here. + // JavaScript things... + var currObj = this; + //paths.enter().append("svg:path").attr("class", "sector"); + //canvas.selectAll("path.sector") + paths.on("click", function (pieData) { + //piedData has the data encapsulated inside the data property. + var pointData = pieData.data; + if (pointData.callBack != null && pointData.callBack.length != '') { + var $container = $(canvas[0]).parent(); + $container.empty(); + $('.tooltipdiv').remove(); + var funCallBack = eval(pointData.callBack); + funCallBack(pointData, currObj); + } + }); +}; + +var Pie3DChart = function (data, params, previousDataPoint, breadcrumbs) { + this.originalData = data; + this.previousDataPoint = previousDataPoint; + this.params = params; + this.$container = $('#' + this.params.canvas.containerId); + //Breadcrumb stack: + this.breadCrumbStack = (breadcrumbs == null ) ? [] : breadcrumbs; + pushToStack(previousDataPoint, this); +}; + +Pie3DChart.prototype.drawChart = function () { + var $container = $('#' + this.params.canvas.containerId); // canvas[0] to convert d3 to jquery object + $container.empty(); + $('.tooltipdiv').remove(); + + //TODO better if this is done inside the building function(drawLines) + stretchCanvas(null, this.$container, this.params); + + this.canvas = createCanvas(this.params.canvas.containerId, this.params.canvas); + this.drawPie3D(this.originalData, this.canvas, this.params); + refreshBreadCrumbs(this); +}; + + +Pie3DChart.prototype.drawPie3D = function (data, canvas, param) { + + if (data == null || data.length == 0) { + this.$container.html( "
No data to draw ...
" ); + } + + var duration_transition = 0; + var parameter = createDefaultParamsForGraphPie(param); + var totalValues = 0; + var h = parameter.canvas.height, + w = parameter.canvas.width + + for (var i = 0; i < data.length; i++) { + totalValues = totalValues + data[i].value * 1; + } + + if (parameter.graph.showLabels) { + h = h - 50; + w = w - 150; + } + + var x_center = w / 2; + var y_center = (h / 2 - 50); + var rx = w / 2 - parameter.graph.thickness; + var ry = h / 2 / 2; + + var color = parameter.graph.colorPalette; + var chart = canvas.append('g') + .attr("transform", "translate(0,0)"); + + var group4 = chart.append("g") + .attr("class", "group4") + .attr("id", "salesDonut") + .attr("transform", "translate(7,0)"); + + if (parameter.graph.allowTransition) { + var duration_transition = 100; + } + + var tooltip = null; + if (parameter.graph.showTip) { + tooltip = new ToolTip(); + } + + + Donut3D.draw("salesDonut", Data(), x_center, y_center, rx, ry, param.graph.thickness, + param.graph.gapWidth, duration_transition, + tooltip, parameter, canvas, this); + + + + function getPercent(d) { + return (Math.round(100 * d / totalValues * 10) / 10 + '%'); + } + + function Data() { + return data.map(function (d, i) { + var newcolor; + if (i == parameter.graph.colorPalette.length) { + newcolor = "#000000"; + } else { + newcolor = color[i % parameter.graph.colorPalette.length]; + } + return { + label: (d.datalabel), + datalabel: (d.datalabel), + value: (d.value * 1), + callBack: d.callBack, + //color: (color[i%(parameter.graph.colorPalette.length)]) + color: newcolor + }; + }); + } + + + if (parameter.graph.allowZoom) { + addZoomToCanvas(chart); + } + + if (parameter.graph.showLabels) { + + var thickness = 119 * Math.log(parameter.canvas.height) - 645; + + var group5 = chart.append("g") + .attr("class", "group5") + .attr("transform", "translate(0," + thickness + ")"); + + for (var i = 0; i < data.length; i++) { + var newcolor; + if (i == parameter.graph.colorPalette.length) { + newcolor = "#000000"; + } else { + newcolor = color[i % parameter.graph.colorPalette.length]; + } + group5.append("circle") + .attr("r", 9) + //.attr("height", 15) + .attr("fill", newcolor) + .attr("cx", w) + .attr("cy", (i * 25)); + //.attr("transform", "translate("+param.canvas.width+"," + (i * 25) + ")"); + } + + group5.selectAll("text") + .data(data) + .enter() + .append("text") + .attr("x", w + 30) + .attr("class", "pie-label") + //.attr("y",i*10+50) + .text(function (d, i) { + return d.datalabel + " - " + getPercent(d.value * 1) + }) + .on("mouseover", function (d, i) { + d3.select("#salesDonut") + .select(".topSlice" + i) + .style("fill", d3.hsl("#E87886").darker(0.8)) + .style("stroke", d3.hsl("#E87886").darker(0.8)); + }) + .on("mouseout", function (d, i) { + + var newcolor; + if (i == parameter.graph.colorPalette.length) { + newcolor = "#000000"; + } else { + newcolor = color[i % parameter.graph.colorPalette.length]; + } + + d3.select("#salesDonut") + .select(".topSlice" + i) + .style("fill", d3.hsl(newcolor)) + .style("stroke", d3.hsl(newcolor)); + }) + .attr("transform", function (d, i) { + return "translate(0," + (i * 25 + 5) + ")" + }); + + } + + + if (parameter.graph.useShadows) { + addShadow(group4, "130%", 5); + group4.select('.slices') + .attr("filter", "url(#drop-shadow)"); + } +} + + +var RingChart = function (data, params, previousDataPoint, breadcrumbs) { + this.originalData = data; + this.previousDataPoint = previousDataPoint; + this.params = params; + this.$container = $('#' + this.params.canvas.containerId); + //Breadcrumb stack: + this.breadCrumbStack = (breadcrumbs == null ) ? [] : breadcrumbs; + pushToStack(previousDataPoint, this); +}; + +RingChart.prototype.drawChart = function () { + var $container = $('#' + this.params.canvas.containerId); // canvas[0] to convert d3 to jquery object + $container.empty(); + $('.tooltipdiv').remove(); + + //TODO better if this is done inside the building function(drawLines) + stretchCanvas(null, this.$container, this.params); + + this.canvas = createCanvas(this.params.canvas.containerId, this.params.canvas); + this.drawRing(this.originalData, this.canvas, this.params); + refreshBreadCrumbs(this); +}; + +RingChart.prototype.drawRing = function(data, canvas, param){ + if (data == null || data.length == 0) { + this.$container.html( "
No data to draw ...
" ); + } + + //d3.select('#'+parent).select('svg').remove(); + var parameter = createDefaultParamsForGraphRign(param); + var h = parameter.canvas.height, + w = parameter.canvas.width; + var value = data[0].value; + var ringColor = parameter.graph.ringColor; + var labelColor = parameter.graph.labelColor; + var label = data[0].datalabel; + var diameter1 = parameter.graph.diameter; + + var currObject = this; + + if (parameter.graph.allowZoom) { addZoomToCanvas(canvas); } + + var rp1 = radialProgress(canvas) + //alert(diameter); + .label(label) + //.onClick(onClick1) + .diameter(diameter1) + .value(value) + .render(); + + function radialProgress(canvas) { + var _data=null, + _duration= 0, + _selection, + _margin = {top:20, right:0, bottom:30, left:20}, + __width = parameter.graph.diameter, + __height = parameter.graph.diameter, + _diameter, + _label="", + _fontSize=10; + + if(parameter.graph.allowTransition){_duration= 1000;} + + + var _mouseClick; + + var _value= 0, + _minValue = 0, + _maxValue = 100; + + var _currentArc= 0, _currentArc2= 0, _currentValue=0; + + var _arc = d3.svg.arc() + .startAngle(0 * (Math.PI/180)); //just radians + + var _arc2 = d3.svg.arc() + .startAngle(0 * (Math.PI/180)) + .endAngle(0); //just radians + + + _selection=canvas; + + + function component() { + + _selection.each(function (data) { + + // Select the svg element, if it exists. + var svg = d3.select(this).selectAll("svg").data([data]); + var enter = svg.enter().append("svg").attr("class","radial-svg").append("g"); + + measure(); + + /*if (parameter.graph.useShadows){ + addShadow(enter, "130%", 2); + }*/ + + svg.attr("width", __width) + .attr("height", __height); + + + var background = enter.append("g").attr("class","component") + .attr("cursor","pointer"); + //.on("click",onMouseClick); + + + _arc.endAngle(360 * (Math.PI/180)) + + background.append("rect") + .attr("class","background") + .attr("width", _width) + .attr("height", _height); + + background.append("path") + .attr("transform", "translate(" + _width/2 + "," + _width/2 + ")") + .attr("d", _arc); + + if (currObject.params.graph.showLabel) { + background.append("text") + .attr("class", "label") + .attr("transform", "translate(" + _width/2 + "," + (_height + 25) + ")") + .attr("fill", labelColor) + .text(_label); + } + + + var g = svg.select("g") + .attr("transform", "translate(" + _margin.left + "," + _margin.top + ")"); + + + _arc.endAngle(_currentArc); + enter.append("g").attr("class", "arcs"); + var path = svg.select(".arcs").selectAll(".arc").data(data); + path.enter().append("path") + .attr("class","arc") + .attr("fill", ringColor) + //.style("filter", "url(#drop-shadow-ring)") + .attr("transform", "translate(" + _width/2 + "," + _width/2 + ")") + .attr("d", _arc) + .on ('click', function (){ + if (currObject.params.graph.allowDrillDown) { + var pointData = currObject.originalData[0]; + if (pointData.callBack != null && pointData.callBack.length != '') { + var $container = $(canvas[0]).parent(); + $container.empty(); + $('.tooltipdiv').remove(); + var funCallBack = eval(pointData.callBack); + funCallBack(pointData, currObject); + } + + if (currObject.breadCrumbStack.length > 0) { + var clip = canvas.append("defs") + .append("svg:clipPath") + .attr("id", "clip") + .append("svg:rect") + .attr("id", "clip-rect") + .attr("x", "0") + .attr("y", "0") + .attr("width", 50) + .attr("height", 50) + .transition() + .duration(2000) + .attr("width", 500) + .attr("height", 500); + d3.select("svg g").attr('clip-path', 'url(#clip)'); + } + } + }); + + + + //Another path in case we exceed 100% + var path2 = svg.select(".arcs").selectAll(".arc2").data(data); + path2.enter().append("path") + .attr("class","arc2") + //.style("filter", "url(#drop-shadow)") + .attr("transform", "translate(" + _width/2 + "," + _width/2 + ")") + .attr("d", _arc2); + + + enter.append("g").attr("class", "labels"); + var label = svg.select(".labels").selectAll(".label").data(data); + label.enter().append("text") + .attr("class","label") + .attr("y",_width/2+_fontSize/3) + .attr("x",_width/2) + .attr("cursor","pointer") + .attr("width",_width) + // .attr("x",(3*_fontSize/2)) + .text(function (d) { return Math.round((_value-_minValue)/(_maxValue-_minValue)*100) + "%" }) + .style("font-size",_fontSize+"px") + .on("click",onMouseClick); + + + if(parameter.graph.useShadows) + { + addShadow(enter, "150%", 5); + + //----------------------From Internet Explorer 10 + var path1 = svg.selectAll('.arc') + .attr("filter", "url(#drop-shadow)"); + //svg.select(".labels").selectAll('.label') + //.style("text-shadow", "5px 4px 4px black"); + //---------------------------------------------End + } + + + path.exit().transition().duration(500).attr("x",1000).remove(); + + + layout(svg); + + function layout(svg) { + + var ratio=(_value-_minValue)/(_maxValue-_minValue); + var endAngle=Math.min(360*ratio,360); + endAngle=endAngle * Math.PI/180; + + path.datum(endAngle); + path.transition().duration(_duration) + .attrTween("d", arcTween); + + if (ratio > 1) { + path2.datum(Math.min(360*(ratio-1),360) * Math.PI/180); + path2.transition().delay(_duration).duration(_duration) + .attrTween("d", arcTween2); + } + + label.datum(Math.round(ratio*100)); + label.transition().duration(_duration) + .tween("text",labelTween); + + } + + }); + + function onMouseClick(d) { + if (typeof _mouseClick == "function") { + //DL: original call back function commented + //_mouseClick.call(); + alert(1); + } + } + } + + function labelTween(a) { + var i = d3.interpolate(_currentValue, a); + _currentValue = i(0); + + return function(t) { + _currentValue = i(t); + this.textContent = Math.round(i(t)) + "%"; + } + } + + function arcTween(a) { + var i = d3.interpolate(_currentArc, a); + + return function(t) { + _currentArc=i(t); + return _arc.endAngle(i(t))(); + }; + } + + function arcTween2(a) { + var i = d3.interpolate(_currentArc2, a); + + return function(t) { + return _arc2.endAngle(i(t))(); + }; + } + + + function measure() { + _width=_diameter - _margin.right - _margin.left - _margin.top - _margin.bottom; + //_width = _diameter; + _height=_width; + _fontSize=_width*.2; + _arc.outerRadius(_width/2); + _arc.innerRadius(_width/2 * (parameter.graph.gapWidth/100)); + _arc2.outerRadius(_width/2 * .85); + _arc2.innerRadius(_width/2 * .85 - (_width/2 * .15)); + } + + + component.render = function() { + measure(); + component(); + return component; + } + + component.value = function (_) { + if (!arguments.length) return _value; + _value = [_]; + _selection.datum([_value]); + return component; + } + + + component.margin = function(_) { + if (!arguments.length) return _margin; + _margin = _; + return component; + }; + + component.diameter = function(_) { + if (!arguments.length) return _diameter + _diameter = _; + return component; + }; + + component.minValue = function(_) { + if (!arguments.length) return _minValue; + _minValue = _; + return component; + }; + + component.maxValue = function(_) { + if (!arguments.length) return _maxValue; + _maxValue = _; + return component; + }; + + component.label = function(_) { + if (!arguments.length) return _label; + _label = _; + return component; + }; + + component._duration = function(_) { + if (!arguments.length) return _duration; + _duration = _; + return component; + }; + + component.onClick = function (_) { + if (!arguments.length) return _mouseClick; + _mouseClick=_; + return component; + } + + return component; + +} + + +} + +var ToolTip = function (template) { + this.template = template; + if (template == null) { + this.template = "Value: %value%
Data Label: %datalabel%"; + } + this.div = d3.select("body") + .append("div") + .attr("class", "tooltipdiv") + .style("opacity", 0) + .style("width","auto") + .style("height","auto"); +} + +ToolTip.prototype.show = function (funPointData) { + var replacements = {'%value%' : funPointData().value, '%datalabel%' : funPointData().datalabel}; + var tipHtml = this.template.replace(/%\w+%/g, function(all) { return replacements[all] || all;}); + + this.div + .transition() + .duration(200) + .style("opacity", .9); + + this.div + .html(tipHtml) + .style("left", (d3.event.pageX-50) + "px") + .style("top", (d3.event.pageY-55) + "px"); +} + +ToolTip.prototype.hide = function (){ + this.div + .transition() + .duration(500) + .style("opacity", 0); +} + + + +function drawVelocimeter(selector,param){ + window.onload=function(){ + + var gauges = []; + //var dashContainer; + var readings = []; // pretend readings are supplied (named by gauge). + var i = 0; + var interv0 = 0; + var xDim = 0; + + var greenColor = "#107618"; + var yellowColor = "#FFC900"; + var redColor = "#EC4922"; + var darkColor = "#101010"; + var blueColor = "#1030B0"; + var dimBlueColor = "#101560"; + var lightColor = "#EEEEEE"; + var greyColor = "303030"; + var darkGreyColor = "101010"; + var blackColor = "000000"; + var lightBlueColor = "7095F0"; + + //InitDim(); + createDashboard(selector, param); + //interv0 = setInterval(updateGauges, 1000); // set a basic interval period + + function createDashboard(selector, param) { + createDash(selector, param); + createGauge(dashContainer, 25, "inbox", "Inbox", 72, 145,90, { + from: 0, to: 25 }, { + from: 25, to: 50 }, { + from: 50, to: 100}); + createGauge(dashContainer, 50, "cases", "Cases", 72, 505,90, {// third is +size bias. + from: 0, to: 25 }, { + from: 25, to: 50 }, { + from: 50, to: 100}); + createGauge(dashContainer, 100, "drafts", "Drafts", 72, 860,90, { + from: 0, to: 25 }, { + from: 25, to: 50 }, { + from: 50, to: 100}); + } + + function updateGauges() { + if (i >= 0) { // initially use a faster interval and sweep the gauge + { + for (var key in gauges) { + gauges[key].redraw(i); + } + if (i === 0) { + clearInterval(interv0); + interv0 = setInterval(updateGauges, 75); + } + i = i + 5; + if (i > 100) { + i = -1; + clearInterval(interv0); + interv0 = setInterval(updateGauges, 1000); // restore a normal interval + } + } + } else { + // pass a data array to dashboard.js's UpdateDashboard(values for named gauges) + for (var key in gauges) { + readings[key] = readings[key] + 10*Math.random()-5; + if (readings[key]<0) + readings[key] = 0; + if (readings[key]>100) + readings[key] = 100; + gauges[key].redraw(readings[key]); + } + } + } + + // code below here could go in a dashboard.js + + function dimChange() { + dimDash(this.selectedIndex); + for (var key in gauges) { + gauges[key].dimDisplay(this.selectedIndex); // just use the index; could use the indexed entry value. + } + } + + function InitDim() { + var dimOptions = { "Day": 0, "Night": 1 }; + + var selectUI = d3.select("#dimmable").append("form").append("select").on("change", dimChange); + selectUI.selectAll("option").data(d3.keys(dimOptions)).enter().append("option").text(function (d) { return d; }); + + selectUI.selectAll("option").data(d3.values(dimOptions)).attr("value", function (d) { return d; }); + + var checkOption = function (e) { + if (e === xDim) { return d3.select(this).attr("selected", "selected"); } + }; + + selectUI.selectAll("option").each(checkOption); + } + + // some of createGauge is specific to the example (size=120), some belongs in Gauge. + function createDash(selector, param) + { + if (param.canvas.stretch) { + this.body = d3.select("#"+selector) + .append("svg:svg") + .attr('width', '100%') + .attr('height', '98%') + .attr("viewBox", "0 0 " + param.canvas.width + " " + 180) + .attr("preserveAspectRatio", "xMidYMid meet") + .attr("pointer-events", "all"); + + }else{ + this.body = d3.select("#"+selector) + .append("svg:svg") + .attr("class", "dash") + .attr("width", param.canvas.width)//this.config.size) + .attr("height", param.canvas.height);// this.config.size); + } + + dashContainer = this.body.append("svg:g").attr("class", "dashContainer") + .attr("width",404) + .attr("height",202); + + if (param.graph.allowZoom) { + addZoomToCanvas(dashContainer); + } + } + + function dimDash(value) { + var dasharea =d3.select("#dashboardContainer").selectAll("ellipse"); + dasharea.style("fill",value<0.5 ? blueColor: dimBlueColor); + } + + function createGauge(myContainer, value, name, label, sizebias, containerOffsetx, containerOffsety, redZone, yellowZone, greenZone) { + var config = { + size: 120 + sizebias, + cx: containerOffsetx, + cy: containerOffsety, + label: label, + minorTicks: 5 + }; + + config.redZones = []; // allows for example upper and lower limit zones + config.redZones.push(redZone); + + config.yellowZones = []; + config.yellowZones.push(yellowZone); + + config.greenZones = []; + config.greenZones.push(greenZone); + + gauges[name] = new Gauge(myContainer, name, config,value); + gauges[name].render(); + readings[name] = 50; + } + + // code from gauge.js, below + // + function Gauge(myContainer, name, configuration, value) { + this.name = name; + this.myContainer = myContainer; + + var self = this; // some internal d3 functions do not "like" the "this" keyword, hence setting a local variable + + this.configure = function (configuration) { + this.config = configuration; + + this.config.size = this.config.size * 0.9; + + this.config.raduis = this.config.size * 0.97 / 2; + this.config.cx = this.config.cx;// + this.config.size / 4; + this.config.cy = this.config.cy;// + this.config.size / 2; + + this.config.min = configuration.min || 0; + this.config.max = configuration.max || 100; + this.config.range = this.config.max - this.config.min; + + this.config.majorTicks = configuration.majorTicks || 5; + this.config.minorTicks = configuration.minorTicks || 2; + + this.config.bezelColor = configuration.bezelColor || lightColor; + this.config.bezelDimColor = configuration.bezelDimColor || greyColor; + this.config.greenColor = configuration.greenColor || greenColor; + this.config.yellowColor = configuration.yellowColor || yellowColor; + this.config.redColor = configuration.redColor || redColor; + this.config.faceColor = configuration.faceColor || lightColor; + this.config.dimFaceColor = configuration.dimFaceColor || darkGreyColor; + this.config.lightColor = configuration.lightColor || "#EEEEEE"; + this.config.greyColor = configuration.greyColor || "101010"; + this.config.lightBlueColor = configuration.lightBlueColor || "6085A0"; + + }; + //alert(value); + + this.render = function () { + this.body = this.myContainer//dashContainer//d3.select("#" + this.placeholderName) + .append("svg:svg") + .attr("class", "gauge") + .attr("x", this.myContainer.x)//this.config.cx-this.config.size/4) + .attr("y", this.myContainer.y)//this.config.cy-this.config.size/4) + .attr("width", this.myContainer.width)//this.config.size) + .attr("height", this.myContainer.height)//this.config.size); + + this.body.append("svg:circle") // outer shell + .attr("cx", this.config.cx) + .attr("cy", this.config.cy) + .attr("r", this.config.raduis) + .style("fill", "#ccc") + .style("stroke", blackColor ) + .style("stroke-width", "0.5px"); + + this.body.append("svg:circle") // bezel + .attr("cx", this.config.cx) + .attr("cy", this.config.cy) + .attr("r", 0.9 * this.config.raduis) + .style("fill", (xDim < 0.5 ? this.config.bezelColor : this.config.bezelDimColor)) + .style("stroke", "#e0e0e0") + .style("stroke-width", "2px"); + + var faceContainer = this.body.append("svg:g").attr("class", "faceContainer"); // for day/night changes + var bandsContainer = this.body.append("svg:g").attr("class", "bandsContainer"); // for day/night changes + var ticksContainer = this.body.append("svg:g").attr("class", "ticksContainer"); // for day/night changes + this.redrawDimmableFace(xDim);//0); + + var pointerContainer = this.body.append("svg:g").attr("class", "pointerContainer"); + //alert(value); + this.drawPointer(value); + pointerContainer.append("svg:circle") + .attr("cx", this.config.cx) + .attr("cy", this.config.cy) + .attr("r", 0.12 * this.config.raduis) + .style("fill", "#4684EE") + .style("stroke", "#666") + .style("opacity", 1); + }; + + this.drawBands = function(bandsContainer) { + for (var index in this.config.greenZones) { + this.drawBand(bandsContainer,this.config.greenZones[index].from, this.config.greenZones[index].to, self.config.greenColor); + } + + for (var index in this.config.yellowZones) { + this.drawBand(bandsContainer,this.config.yellowZones[index].from, this.config.yellowZones[index].to, self.config.yellowColor); + } + + for (var index in this.config.redZones) { + this.drawBand(bandsContainer,this.config.redZones[index].from, this.config.redZones[index].to, self.config.redColor); + } + }; + + this.redrawDimmableFace = function (value) { + this.drawFace(value < 0.5 ? self.config.faceColor : self.config.dimFaceColor, // facecolor + value < 0.5 ? self.config.greyColor : lightBlueColor); + } + + this.drawTicks = function (ticksContainer,color) { + + var fontSize = Math.round(this.config.size / 16); + var majorDelta = this.config.range / (this.config.majorTicks - 1); + for (var major = this.config.min; major <= this.config.max; major += majorDelta) { + var minorDelta = majorDelta / this.config.minorTicks; + for (var minor = major + minorDelta; minor < Math.min(major + majorDelta, this.config.max); minor += minorDelta) { + var minorpoint1 = this.valueToPoint(minor, 0.75); + var minorpoint2 = this.valueToPoint(minor, 0.85); + + ticksContainer.append("svg:line") + .attr("x1", minorpoint1.x) + .attr("y1", minorpoint1.y) + .attr("x2", minorpoint2.x) + .attr("y2", minorpoint2.y) + .style("stroke", color) + .style("stroke-width", "1px"); + } + + var majorpoint1 = this.valueToPoint(major, 0.7); + var majorpoint2 = this.valueToPoint(major, 0.85); + + ticksContainer.append("svg:line") + .attr("x1", majorpoint1.x) + .attr("y1", majorpoint1.y) + .attr("x2", majorpoint2.x) + .attr("y2", majorpoint2.y) + .style("stroke", color) + .style("stroke-width", "2px"); + + if (major == this.config.min || major == this.config.max) { + var point = this.valueToPoint(major, 0.63); + + ticksContainer.append("svg:text") + .attr("x", point.x) + .attr("y", point.y) + .attr("dy", fontSize / 3) + .attr("text-anchor", major == this.config.min ? "start" : "end") + .text(major) + .style("font-size", fontSize + "px") + .style("fill", color) + .style("stroke-width", "0px"); + } + } + }; + + + this.redraw = function (value) { + this.drawPointer(value); + }; + + this.dimDisplay = function (value) { + this.redrawDimmableFace(value); + }; + + this.drawBand = function (bandsContainer, start, end, color) { + if (0 >= end - start) return; + + bandsContainer.append("svg:path") + .style("fill", color) + .attr("d", d3.svg.arc() + .startAngle(this.valueToRadians(start)) + .endAngle(this.valueToRadians(end)) + .innerRadius(0.70 * this.config.raduis) + .outerRadius(0.85 * this.config.raduis)) + .attr("transform", function () { + return "translate(" + self.config.cx + ", " + self.config.cy + ") rotate(270)"; + }); + }; + + this.drawFace = function (colorFace,colorTicks) { + var arc0 = d3.svg.arc() + .startAngle(0) //this.valueToRadians(0)) + .endAngle(2 * Math.PI) + .innerRadius(0.00 * this.config.raduis) + .outerRadius(0.9 * this.config.raduis); + + var faceContainer = this.body.selectAll(".faceContainer"); + var bandsContainer = this.body.selectAll(".bandsContainer"); + var ticksContainer = this.body.selectAll(".ticksContainer"); + var pointerContainer = this.body.selectAll(".pointerContainer"); + var face = faceContainer.selectAll("path"); + if (face == 0) + { + faceContainer + .append("svg:path") + .attr("d", arc0) //d3.svg.arc() + .style("fill", colorFace) + .style("fill-opacity", 0.7) + .attr("transform", + "translate(" + self.config.cx + ", " + self.config.cy + ")"); + + this.drawBands(bandsContainer); + this.drawTicks(ticksContainer,colorTicks); + var fontSize = Math.round(this.config.size / 9); + faceContainer.append("svg:text") + .attr("x", this.config.cx) + .attr("y", this.config.cy - this.config.size/6 - fontSize / 2 ) + .attr("dy", fontSize / 2) + .attr("text-anchor", "middle") + .text(this.config.label) + .style("font-size", fontSize + "px") + .style("fill", colorTicks) + .style("stroke-width", "0px"); + } + else + { + face.style("fill", colorFace); + var facetxt = faceContainer.selectAll("text"); + facetxt.style("fill", colorTicks); + var ptrtxt = pointerContainer.selectAll("text"); + ptrtxt.style("fill", colorTicks); + var ticks = ticksContainer.selectAll("line"); + ticks.style("stroke", colorTicks); + var texts = ticksContainer.selectAll("text"); + texts.style("fill", colorTicks); + + } + }; + + this.drawPointer = function (value) { + var delta = this.config.range / 13; + + var head = this.valueToPoint(value, 0.85); + var head1 = this.valueToPoint(value - delta, 0.12); + var head2 = this.valueToPoint(value + delta, 0.12); + + var tailValue = value - (this.config.range * (1 / (270 / 360)) / 2); + var tail = this.valueToPoint(tailValue, 0.28); + var tail1 = this.valueToPoint(tailValue - delta, 0.12); + var tail2 = this.valueToPoint(tailValue + delta, 0.12); + + var data = [head, head1, tail2, tail, tail1, head2, head]; + + var line = d3.svg.line() + .x(function (d) { + return d.x; + }) + .y(function (d) { + return d.y; + }) + .interpolate("basis"); + + var pointerContainer = this.body.select(".pointerContainer"); + + var pointer = pointerContainer.selectAll("path").data([data]); + + pointer.enter() + .append("svg:path") + .attr("d", line) + .style("fill", "#dc3912") + .style("stroke", "#c63310") + .style("fill-opacity", 0.7); + + pointer.transition() + .attr("d", line) + //.ease("linear") + .duration(i>=0 ? 50 : 500); + + var fontSize = Math.round(this.config.size / 10); + pointerContainer.selectAll("text") + .data([value]) + .text(Math.round(value)) + .enter() + .append("svg:text") + .attr("x", this.config.cx) + .attr("y", this.config.cy + this.config.size/6 + fontSize) + .attr("dy", fontSize / 2) + .attr("text-anchor", "middle") + .text(Math.round(value)) + .style("font-size", fontSize + "px") + .style("fill", "#000") + .style("stroke-width", "0px"); + }; + + this.valueToDegrees = function (value) { + return value / this.config.range * 270 - 45; + }; + + this.valueToRadians = function (value) { + return this.valueToDegrees(value) * Math.PI / 180; + }; + + this.valueToPoint = function (value, factor) { + var len = this.config.raduis * factor; + var inRadians = this.valueToRadians(value); + var point = { + x: this.config.cx - len * Math.cos(inRadians), + y: this.config.cy - len * Math.sin(inRadians) + }; + + return point; + }; + + // initialization + this.configure(configuration); + } + +} +} + +!function(){ + var Donut3D={}; + + function pieTop(d, rx, ry, ir ){ + d.endAngle = d.endAngle - 0.001; + if(d.endAngle - d.startAngle == 0 ) return "M 0 0"; + var sx = rx*Math.cos(d.startAngle), + sy = ry*Math.sin(d.startAngle), + ex = rx*Math.cos(d.endAngle), + ey = ry*Math.sin(d.endAngle); + + var ret =[]; + ret.push("M",sx,sy,"A",rx,ry,"0",(d.endAngle-d.startAngle > Math.PI? 1: 0),"1",ex,ey,"L",ir*ex,ir*ey); + ret.push("A",ir*rx,ir*ry,"0",(d.endAngle-d.startAngle > Math.PI? 1: 0), "0",ir*sx,ir*sy,"z"); + return ret.join(" "); + } + + function pieOuter(d, rx, ry, h ){ + var startAngle = (d.startAngle > Math.PI ? Math.PI : d.startAngle); + var endAngle = (d.endAngle > Math.PI ? Math.PI : d.endAngle); + + var sx = rx*Math.cos(startAngle), + sy = ry*Math.sin(startAngle), + ex = rx*Math.cos(endAngle), + ey = ry*Math.sin(endAngle); + + var ret =[]; + ret.push("M",sx,h+sy,"A",rx,ry,"0 0 1",ex,h+ey,"L",ex,ey,"A",rx,ry,"0 0 0",sx,sy,"z"); + return ret.join(" "); + } + + function pieInner(d, rx, ry, h, ir ){ + var startAngle = (d.startAngle < Math.PI ? Math.PI : d.startAngle); + var endAngle = (d.endAngle < Math.PI ? Math.PI : d.endAngle); + + var sx = ir*rx*Math.cos(startAngle), + sy = ir*ry*Math.sin(startAngle), + ex = ir*rx*Math.cos(endAngle), + ey = ir*ry*Math.sin(endAngle); + + var ret =[]; + ret.push("M",sx, sy,"A",ir*rx,ir*ry,"0 0 1",ex,ey, "L",ex,h+ey,"A",ir*rx, ir*ry,"0 0 0",sx,h+sy,"z"); + return ret.join(" "); + } + + function getPercent(d){ + return (d.endAngle-d.startAngle > 0.2 ? + Math.round(1000*(d.endAngle-d.startAngle)/(Math.PI*2))/10+'%' : ''); + } + + Donut3D.transition = function(id, data, rx, ry, h, ir){ + function arcTweenInner(a) { + var i = d3.interpolate(this._current, a); + this._current = i(0); + return function(t) { return pieInner(i(t), rx+0.5, ry+0.5, h, ir); }; + } + function arcTweenTop(a) { + var i = d3.interpolate(this._current, a); + this._current = i(0); + return function(t) { return pieTop(i(t), rx, ry, ir); }; + } + function arcTweenOuter(a) { + var i = d3.interpolate(this._current, a); + this._current = i(0); + return function(t) { return pieOuter(i(t), rx-.5, ry-.5, h); }; + } + function textTweenX(a) { + var i = d3.interpolate(this._current, a); + this._current = i(0); + return function(t) { return 0.6*rx*Math.cos(0.5*(i(t).startAngle+i(t).endAngle)); }; + } + function textTweenY(a) { + var i = d3.interpolate(this._current, a); + this._current = i(0); + return function(t) { return 0.6*rx*Math.sin(0.5*(i(t).startAngle+i(t).endAngle)); }; + } + + var _data = d3.layout.pie().sort(null).value(function(d) {return d.value;})(data); + + d3.select("#"+id).selectAll(".innerSlice").data(_data) + .transition().duration(750).attrTween("d", arcTweenInner); + + d3.select("#"+id).selectAll(".topSlice").data(_data) + .transition().duration(750).attrTween("d", arcTweenTop); + + d3.select("#"+id).selectAll(".outerSlice").data(_data) + .transition().duration(750).attrTween("d", arcTweenOuter); + + d3.select("#"+id).selectAll(".percent").data(_data).transition().duration(750) + .attrTween("x",textTweenX).attrTween("y",textTweenY).text(getPercent); + } + + Donut3D.draw=function(id, data, x /*center x*/, y/*center y*/, + rx/*radius x*/, ry/*radius y*/, h/*height*/, ir/*inner radius*/, dt/*duration transition*/, + tip/*tooltip*/, parameter /*chart conf. parameters*/, + canvas /*place where the pie is drawn*/, currObj /*Pie3D object*/){ + + var _data = d3.layout.pie().sort(null).value(function(d) {return d.value;})(data); + + var slices = d3.select("#"+id).append("g").attr("transform", "translate(" + x + "," + y + ")") + .attr("class", "slices"); + + slices.selectAll(".innerSlice").data(_data).enter().append("path") + .transition().delay(function(d, i) { return i * dt; }).duration(dt*5) + .attr("class", "innerSlice") + .style("fill", function(d) { return d3.hsl(d.data.color).darker(0.7); }) + .attr("d",function(d){ return pieInner(d, rx+0.5,ry+0.5, h, ir);}) + .each(function(d){this._current=d;}); + + //.on('mouseover', tip.show) + // .on('mouseout', tip.hide) + // TODO set tooltip here + slices.selectAll(".topSlice").data(_data).enter().append("path") + .on('mouseover', function (d) { + if (parameter.graph.showTip) { + tip.show(function () { + return { + value: d.data.value, + datalabel: d.data.datalabel + } + }); + } + }) + .on('mouseout', function () { + if (parameter.graph.showTip) { + tip.hide(); + } + }) + .on('click', function (d) { + if (parameter.graph.allowDrillDown) { + var pointData = d.data; + if (pointData.callBack != null && pointData.callBack.length != '') { + var $container = $(canvas[0]).parent(); + $container.empty(); + $('.tooltipdiv').remove(); + var funCallBack = eval(pointData.callBack); + funCallBack(pointData, currObj); + } + } + }) + .transition().delay(function(d, i) { return i * dt; }).duration(dt*5) + .attr("class", function(d,i){return "topSlice"+i}) + .style("fill", function(d) { return d.data.color; }) + .style("stroke", function(d) { return d.data.color; }) + .attr("d",function(d){ return pieTop(d, rx, ry, ir);}) + .each(function(d){this._current=d;}); + + slices.selectAll(".outerSlice").data(_data).enter().append("path") + .transition().delay(function(d, i) { return i * dt; }).duration(dt*5) + .attr("class", "outerSlice") + .style("fill", function(d) { return d3.hsl(d.data.color).darker(0.7); }) + .attr("d",function(d){ return pieOuter(d, rx-.5,ry-.5, h);}) + .each(function(d){this._current=d;}); + + slices.selectAll(".percent").data(_data).enter().append("text") + .transition().delay(function(d, i) { return i * dt; }).duration(dt*5) + .attr("class", "percent") + .attr("x",function(d){ return 0.6*rx*Math.cos(0.5*(d.startAngle+d.endAngle));}) + .attr("y",function(d){ return 0.6*ry*Math.sin(0.5*(d.startAngle+d.endAngle));}) + .text(getPercent).each(function(d){this._current=d;}); + + } + + this.Donut3D = Donut3D; +}(); + diff --git a/workflow/engine/classes/class.dashboards.php b/workflow/engine/classes/class.dashboards.php new file mode 100644 index 000000000..12ef77820 --- /dev/null +++ b/workflow/engine/classes/class.dashboards.php @@ -0,0 +1,150 @@ +addSelectColumn('COUNT(*) AS CNT'); + $criteria->add(DashboardPeer::DAS_STATUS, array('2'), Criteria::NOT_IN); + + $dataset = DashboardPeer::DoSelectRs($criteria); + $dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $dataset->next(); + $row = $dataset->getRow(); + $totalRows = $row['CNT']; + + $criteria->clearSelectColumns(); + $criteria->addSelectColumn(DashboardPeer::DAS_UID); + $criteria->addSelectColumn(DashboardPeer::DAS_TITLE); + $criteria->addSelectColumn(DashboardPeer::DAS_DESCRIPTION); + $criteria->addSelectColumn(DashboardPeer::DAS_UPDATE_DATE); + $criteria->addSelectColumn(DashboardPeer::DAS_STATUS); + + $criteria->add(DashboardPeer::DAS_STATUS, array('2'), Criteria::NOT_IN); + + if ($sort != '') { + if ($dir == 'ASC') { + $criteria->addAscendingOrderByColumn($sort); + } else { + $criteria->addDescendingOrderByColumn($sort); + } + } + $criteria->setOffset($start); + $criteria->setLimit($limit); + $dataset = DashboardPeer::DoSelectRs($criteria); + $dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + + $rows = Array(); + $user = new Users(); + $group = new Groupwf(); + $owner = new DashboardDasInd(); + while ($dataset->next()) { + $row = $dataset->getRow(); + $row['DAS_OWNER'] = ''; + try { + $ownerDetail = $owner->loadByDashboards($row['DAS_UID']); + foreach ($ownerDetail as $key => $value) { + $title = ''; + $detail = ''; + if ($value['OWNER_TYPE'] == 'USER') { + $detail = $user->load($value['OWNER_UID']); + $title = $detail['USR_FIRSTNAME'] . ' '. $detail['USR_LASTNAME']; + } else if ($value['OWNER_TYPE'] == 'GROUP') { + $detail = $group->load($value['OWNER_UID']); + $title = $detail['GRP_TITLE']; + } + $row['DAS_OWNER'] .= ($row['DAS_OWNER'] == '') ? $title : ', ' . $title; + } + + } catch (exception $oError) { + // + } + + $row['DAS_LABEL_STATUS'] = ($row['DAS_STATUS'] == 1) ? G::loadTranslation('ID_ACTIVE') : G::loadTranslation('ID_INACTIVE'); + + $rows[] = $row; + } + $response = Array(); + $response['totalCount'] = $totalRows; + $response['start'] = $start; + $response['limit'] = $limit; + $response['sort'] = G::toLower($sort); + $response['dir'] = G::toLower($dir); + $response['data'] = $rows; + + return $response; + } + + + public function getOwnerByDasUid ($das_uid='', $start=0, $limit=20, $search='') + { + require_once 'classes/model/Users.php'; + require_once 'classes/model/Groupwf.php'; + require_once 'classes/model/DashboardDasInd.php'; + + $das_uid = isset($_REQUEST['das_uid']) ? $_REQUEST['das_uid'] : $das_uid; + $start = isset($_REQUEST['start']) ? $_REQUEST['start'] : $start; + $limit = isset($_REQUEST['limit']) ? $_REQUEST['limit'] : $limit; + $search = isset($_REQUEST['search']) ? $_REQUEST['search'] : $search; + + $criteria = new Criteria('workflow'); + $criteria->addSelectColumn('COUNT(*) AS TOTAL'); + $criteria->add(DashboardDasIndPeer::DAS_UID, $das_uid, Criteria::EQUAL); + + $dataset = DashboardDasIndPeer::DoSelectRs($criteria); + $dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $dataset->next(); + $row = $dataset->getRow(); + $totalRows = $row['TOTAL']; + + $criteria->clearSelectColumns(); + $criteria->add(DashboardDasIndPeer::DAS_UID, $das_uid, Criteria::EQUAL); + + $criteria->setOffset($start); + $criteria->setLimit($limit); + $dataset = DashboardDasIndPeer::DoSelectRs($criteria); + $dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + + $rows = Array(); + $user = new Users(); + $group = new Groupwf(); + while ($dataset->next()) { + $row = $dataset->getRow(); + $row['OWNER_LABEL'] = '---'; + try { + if ($row['OWNER_TYPE'] == 'USER') { + $detail = $user->load($row['OWNER_UID']); + $row['OWNER_LABEL'] = $detail['USR_FIRSTNAME'] . ' '. $detail['USR_LASTNAME']; + } else if ($row['OWNER_TYPE'] == 'GROUP') { + $detail = $group->load($row['OWNER_UID']); + $row['OWNER_LABEL'] = $detail['GRP_TITLE']; + } + } catch (exception $oError) { + // + } + $rows[] = $row; + } + $response = Array(); + $response['totalCount'] = $totalRows; + $response['start'] = $start; + $response['limit'] = $limit; + $response['data'] = $rows; + + return $response; + } + +} diff --git a/workflow/engine/classes/class.indicatorsCalculator.php b/workflow/engine/classes/class.indicatorsCalculator.php new file mode 100644 index 000000000..2f4674f3d --- /dev/null +++ b/workflow/engine/classes/class.indicatorsCalculator.php @@ -0,0 +1,755 @@ +getConstants(); + } + return self::$constCacheArray[$calledClass]; + } + + public static function isValidName($name, $strict = false) { + $constants = self::getConstants(); + + if ($strict) { + return array_key_exists($name, $constants); + } + + $keys = array_map('strtolower', array_keys($constants)); + return in_array(strtolower($name), $keys); + } + + public static function isValidValue($value) { + $values = array_values(self::getConstants()); + return in_array($value, $values, $strict = true); + } +} + + +abstract class ReportingPeriodicityEnum extends BasicEnum { + //100s space to easy add more periods if in the future new periods are needed + const NONE = 0; + const MONTH = 100; + const QUARTER = 200; + const SEMESTER = 300; + const YEAR = 400; + + public static function fromValue($value) { + if ($value == ReportingPeriodicityEnum::NONE) return ReportingPeriodicityEnum::NONE; + if ($value == ReportingPeriodicityEnum::MONTH) return ReportingPeriodicityEnum::MONTH; + if ($value == ReportingPeriodicityEnum::QUARTER) return ReportingPeriodicityEnum::QUARTER; + if ($value == ReportingPeriodicityEnum::SEMESTER) return ReportingPeriodicityEnum::SEMESTER; + if ($value == ReportingPeriodicityEnum::YEAR) return ReportingPeriodicityEnum::YEAR; + return ReportingPeriodicityEnum::MONTH; + } + + public static function labelFromValue($value) { + if ($value == ReportingPeriodicityEnum::MONTH) return "ID_MONTH" ; + if ($value == ReportingPeriodicityEnum::QUARTER) return "ID_QUARTER"; + if ($value == ReportingPeriodicityEnum::SEMESTER) return "ID_SEMESTER"; + if ($value == ReportingPeriodicityEnum::YEAR) return "ID_YEAR"; + return "ID_MONTH"; + } +} + +abstract class IndicatorDataSourcesEnum extends BasicEnum { + //100s space to easy add more periods if in the future new periods are needed + const USER = 0; + const PROCESS = 100; + const PROCESS_CATEGORY = 200; + const USER_GROUP = 300; +} + +class indicatorsCalculator +{ + private static $connectionName = 'workflow'; + + private $userReportingMetadata = array("tableName" => "USR_REPORTING", "keyField" => "USR_UID"); + private $processReportingMetadata = array("tableName" => "PRO_REPORTING", "keyField" => "PRO_UID"); + private $userGroupReportingMetadata = array("tableName" => "USR_REPORTING", "keyField" => "USR_UID"); + private $processCategoryReportingMetadata = array("tableName" => "PRO_REPORTING", "keyField" => "PRO_UID"); + + private $peiCostFormula = "SUM(TOTAL_CASES_OUT * CONFIGURED_TASK_TIME - TOTAL_TIME_BY_TASK * USER_HOUR_COST)"; + private $peiFormula = "SUM(TOTAL_CASES_OUT*CONFIGURED_TASK_TIME) / SUM(SDV_TIME * TOTAL_CASES_OUT + TOTAL_TIME_BY_TASK)"; + + private $ueiCostFormula = "SUM(TOTAL_CASES_OUT * CONFIGURED_TASK_TIME - TOTAL_TIME_BY_TASK * USER_HOUR_COST)"; + private $ueiFormula = "SUM(TOTAL_CASES_OUT * CONFIGURED_TASK_TIME) / SUM(TOTAL_TIME_BY_TASK * USER_HOUR_COST)"; + +// +// public function processEfficiencyIndex($processList, $initDate, $endDate) +// { +// $resultList = $this->processEfficiencyIndexList($processList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return ($resultList[0]['PEI']); +// } + + public function peiHistoric($processId, $initDate, $endDate, $periodicity) { + if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); + if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); + + $sqlString = $this->indicatorsBasicQueryBuilder(IndicatorDataSourcesEnum::USER + , $processId, $periodicity, $initDate, $endDate + , $this->peiFormula); + + $returnValue = $this->propelExecutor($sqlString); + return $returnValue; + } + + public function indicatorData($indicatorId) + { + $sqlString = "select * from DASHBOARD_INDICATOR where DAS_IND_UID= '$indicatorId'"; + $retval = $this->propelExecutor($sqlString); + return $retval; + } + + public function peiProcesses($indicatorId, $initDate, $endDate, $language) + { + if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); + if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); + + $initYear = $initDate->format("Y"); + $initMonth = $initDate->format("m"); + $initDay = $endDay = 1; + $endYear = $endDate->format("Y"); + $endMonth = $endDate->format("m"); + + $sqlString = " + select + i.PRO_UID as uid, + tp.CON_VALUE as name, + efficiencyIndex, + inefficiencyCost + from + ( select + PRO_UID, + $this->peiFormula as efficiencyIndex, + $this->peiCostFormula as inefficiencyCost + from USR_REPORTING + WHERE + ( + PRO_UID = (select DAS_UID_PROCESS from DASHBOARD_INDICATOR where DAS_IND_UID = '$indicatorId') + or + (select DAS_UID_PROCESS from DASHBOARD_INDICATOR where DAS_IND_UID = '$indicatorId')= '0' + ) + AND + IF (`YEAR` = $initYear, `MONTH`, `YEAR`) >= IF (`YEAR` = $initYear, $initMonth, $initYear) + AND + IF(`YEAR` = $endYear, `MONTH`, `YEAR`) <= IF (`YEAR` = $endYear, $endMonth, $endYear) + group by PRO_UID + ) i + left join (select * + from CONTENT + where CON_CATEGORY = 'PRO_TITLE' + and CON_LANG = '$language' + ) tp on i.PRO_UID = tp.CON_ID"; + $retval = $this->propelExecutor($sqlString); + return $retval; + } + + public function ueiUserGroups($indicatorId, $initDate, $endDate, $language) + { + //for the moment all the indicator summarizes ALL users, so indicatorId is not used in this function. + if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); + if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); + + $initYear = $initDate->format("Y"); + $initMonth = $initDate->format("m"); + $initDay = $endDay = 1; + $endYear = $endDate->format("Y"); + $endMonth = $endDate->format("m"); + + //TODO ADD to USR_REPORTING the user's Group to speed up the query. + $sqlString = " + select + IFNULL(i.GRP_UID, '0') as uid, + IFNULL(tp.CON_VALUE, 'No Group') as name, + efficiencyIndex, + inefficiencyCost, + averageTime, + deviationTime + from + ( select + gu.GRP_UID, + $this->ueiFormula as efficiencyIndex, + $this->ueiCostFormula as inefficiencyCost, + AVG(AVG_TIME) as averageTime, + AVG(SDV_TIME) as deviationTime + from USR_REPORTING ur + left join + GROUP_USER gu on gu.USR_UID = ur.USR_UID + WHERE + IF (`YEAR` = $initYear, `MONTH`, `YEAR`) >= IF (`YEAR` = $initYear, $initMonth, $initYear) + AND + IF(`YEAR` = $endYear, `MONTH`, `YEAR`) <= IF (`YEAR` = $endYear, $endMonth, $endYear) + group by gu.GRP_UID + ) i + left join (select * + from CONTENT + where CON_CATEGORY = 'GRP_TITLE' + and CON_LANG = 'en' + ) tp on i.GRP_UID = tp.CON_ID"; + + $retval = $this->propelExecutor($sqlString); + return $retval; + } + + public function groupEmployeesData($groupId, $initDate, $endDate, $language) + { + //TODO what if we are analizing empty user group (users without group) + //for the moment all the indicator summarizes ALL users, so indicatorId is not used in this function. + if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); + if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); + + $initYear = $initDate->format("Y"); + $initMonth = $initDate->format("m"); + $initDay = $endDay = 1; + $endYear = $endDate->format("Y"); + $endMonth = $endDate->format("m"); + + $sqlString = " select + i.USR_UID as uid, + i.name, + efficiencyIndex, + inefficiencyCost, + averageTime, + deviationTime + from + ( select + u.USR_UID, + concat(u.USR_FIRSTNAME, ' ', u.USR_LASTNAME) as name, + $this->ueiFormula as efficiencyIndex, + $this->ueiCostFormula as inefficiencyCost, + AVG(AVG_TIME) as averageTime, + AVG(SDV_TIME) as deviationTime + from USR_REPORTING ur + left join + GROUP_USER gu on gu.USR_UID = ur.USR_UID + LEFT JOIN USERS u on u.USR_UID = ur.USR_UID + where (gu.GRP_UID = '$groupId' or ('$groupId' = '0' && gu.GRP_UID is null )) + AND + IF (`YEAR` = $initYear, `MONTH`, `YEAR`) >= IF (`YEAR` = $initYear, $initMonth, $initYear) + AND + IF(`YEAR` = $endYear, `MONTH`, `YEAR`) <= IF (`YEAR` = $endYear, $endMonth, $endYear) + group by ur.USR_UID + ) i"; + $returnValue = $this->propelExecutor($sqlString); + return $returnValue; + } +// +// public function employeeEfficiencyIndex($employeeList, $initDate, $endDate) +// { +// $resultList = $this->employeeEfficiencyIndexList($employeeList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($resultList)); +// } + + public function ueiHistoric($employeeId, $initDate, $endDate, $periodicity) + { + if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); + if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); + + $sqlString = $this->indicatorsBasicQueryBuilder(IndicatorDataSourcesEnum::USER + , $employeeId, $periodicity, $initDate, $endDate + , $this->ueiFormula); + $returnValue = $this->propelExecutor($sqlString); + return $returnValue; + } + +// public function employeeEfficiencyCost($employeeList, $initDate, $endDate) +// { +// $resultList = $this->employeeEfficiencyCostList($employeeList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($resultList)); +// } +// +// public function userCostByGroupHistoric($groupId, $initDate, $endDate, $periodicity) { +// if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); +// if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); +// +// $periodicitySelectFields = $this->periodicityFieldsForSelect($periodicity); +// $periodicityGroup = $this->periodicityFieldsForGrouping($periodicity); +// $initYear = $initDate->format("Y"); +// $initMonth = $initDate->format("m"); +// $initDay = $endDay = 1; +// $endYear = $endDate->format("Y"); +// $endMonth = $endDate->format("m"); +// +// $filterCondition = ""; +// if ($groupId != null && $groupId > 0) { +// $filterCondition = " AND GRP_UID = '$groupId'"; +// } +// +// $sqlString = "SELECT (SUM(CONFIGURED_TASK_TIME) - SUM(TOTAL_TIME_BY_TASK)) * USER_HOUR_COST as EEC +// FROM USR_REPORTING ur +// LEFT JOIN GROUP_USER gu on gu.USR_UID =ur.USR_UID +// LEFT JOIN GROUP_USER gu on gu.USR_UID =ur.USR_UID +// WHERE +// IF (`YEAR` = $initYear, `MONTH`, `YEAR`) >= IF (`YEAR` = $initYear, $initMonth, $initYear) +// AND +// IF(`YEAR` = $endYear, `MONTH`, `YEAR`) <= IF (`YEAR` = $endYear, $endMonth, $endYear)" +// . $filterCondition +// . $periodicityGroup; +// $returnValue = $this->propelExecutor($sqlString); +// return $returnValue; +// } + +// public function processEfficiencyCost($processList, $initDate, $endDate) +// { +// $resultList = $this->processEfficiencyCostList($processList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($resultList)); +// } + + public function peiCostHistoric($processId, $initDate, $endDate, $periodicity) + { + if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); + if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); + + $periodicitySelectFields = $this->periodicityFieldsForSelect($periodicity); + $periodicityGroup = $this->periodicityFieldsForGrouping($periodicity); + $initYear = $initDate->format("Y"); + $initMonth = $initDate->format("m"); + $initDay = $endDay = 1; + $endYear = $endDate->format("Y"); + $endMonth = $endDate->format("m"); + + $filterCondition = ""; + if ($processId != null && $processId > 0) { + $filterCondition = " AND PRO_UID = '$processId'"; + } + + $sqlString = "SELECT $periodicitySelectFields " . $this->peiCostFormula . " as PEC + FROM USR_REPORTING + WHERE + IF (`YEAR` = $initYear, `MONTH`, `YEAR`) >= IF (`YEAR` = $initYear, $initMonth, $initYear) + AND + IF(`YEAR` = $endYear, `MONTH`, `YEAR`) <= IF (`YEAR` = $endYear, $endMonth, $endYear)" + . $filterCondition + . $periodicityGroup; + + $retval = $this->propelExecutor($sqlString); + return $retval; + } + + public function generalIndicatorData($indicatorId, $initDate, $endDate, $periodicity) { + if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); + if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); + + $arrayT = $this->indicatorData($indicatorId); + if (sizeof($arrayT) == 0 ) { + return array(); + } + + $indicator = $arrayT[0]; + $indicatorProcessId = $indicator["DAS_UID_PROCESS"]; + $indicatorType = $indicator["DAS_IND_TYPE"]; + if ($indicatorProcessId == "0" || strlen($indicatorProcessId) ==0) { + $indicatorProcessId = null; + } + //$indicatorJson = unserialize($indicator['DAS_IND_PROPERTIES']); + //$indicatorConfig = json_decode($indicatorJson); + + /*$graph1 = $indicatorConfig->{'IND_FIRST_FIGURE'}; + $freq1 = $indicatorConfig->{'IND_FIRST_FREQUENCY'}; + $graph2 = $indicatorConfig->{'IND_SECOND_FIGURE'}; + $freq2 = $indicatorConfig->{'IND_SECOND_FREQUENCY'}; + */ + + $graph1 = $indicator['DAS_IND_FIRST_FIGURE']; + $freq1 = $indicator['DAS_IND_FIRST_FREQUENCY']; + $graph2 = $indicator['DAS_IND_SECOND_FIGURE']; + $freq2 = $indicator['DAS_IND_SECOND_FREQUENCY']; + + $graph1XLabel = G::loadTranslation(ReportingPeriodicityEnum::labelFromValue($freq1)); + $graph1YLabel = "Value"; + + $graph2XLabel = G::loadTranslation(ReportingPeriodicityEnum::labelFromValue($freq2)); + $graph2YLabel = "Value"; + + $graphConfigurationString = "'$graph1XLabel' as graph1XLabel, + '$graph1YLabel' as graph1YLabel, + '$graph2XLabel' as graph2XLabel, + '$graph2YLabel' as graph2YLabel, + '$graph1' as graph1Type, + '$freq1' as frequency1Type, + '$graph2' as graph2Type, + '$freq2' as frequency2Type,"; + + switch ($indicatorType) { + //overdue + case "1050": + $calcField = "$graphConfigurationString 100 * SUM(TOTAL_CASES_OVERDUE) / SUM(TOTAL_CASES_ON_TIME + TOTAL_CASES_OVERDUE) as value"; + break; + //new cases + case "1060": + $calcField = "$graphConfigurationString 100 * SUM(TOTAL_CASES_IN) / SUM(TOTAL_CASES_ON_TIME + TOTAL_CASES_OVERDUE) as value"; + break; + //completed + case "1070": + $calcField = "$graphConfigurationString 100 * SUM(TOTAL_CASES_OUT) / SUM(TOTAL_CASES_ON_TIME + TOTAL_CASES_OVERDUE) as value"; + break; + default: + throw new Exception(" The indicator id '$indicatorId' with type $indicatorType hasn't an associated operation."); + } + + $sqlString = $this->indicatorsBasicQueryBuilder(IndicatorDataSourcesEnum::PROCESS + , $indicatorProcessId, $periodicity + , $initDate, $endDate + , $calcField); + $returnValue = $this->propelExecutor($sqlString); + return $returnValue; + } +// /***** Indicators for overdue, new, completed ******/ +// public function totalOverdueCasesByProcess($processList, $initDate, $endDate) +// { +// $returnList = $this->totalOverdueCasesByProcessList($processList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($returnList)); +// } +// +// public function totalOverdueCasesByProcessList($processList, $initDate, $endDate, $periodicity) +// { +// return $this->sumCasesListByProcess($processList, $initDate, $endDate, $periodicity, "SUM(TOTAL_CASES_OVERDUE)", ""); +// } +// +// public function totalOverdueCasesByUser($userList, $initDate, $endDate) +// { +// $returnList = $this->totalOverdueCasesByUserList($userList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($returnList)); +// } +// +// public function totalOverdueCasesByUserList($userList, $initDate, $endDate, $periodicity) +// { +// return $this->sumCasesListByUser($userList, $initDate, $endDate, $periodicity, "SUM(TOTAL_CASES_OVERDUE)", ""); +// } +// +// //percent +// public function percentOverdueCasesByProcess($processList, $initDate, $endDate) +// { +// $returnList = $this->percentOverdueCasesByProcessList($processList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($returnList)); +// } +// + +// public function percentOverdueCasesByProcessList($processList, $initDate, $endDate, $periodicity) +// { +// return $this->sumCasesListByProcess($processList, $initDate, $endDate, $periodicity, "100 * SUM(TOTAL_CASES_OVERDUE)", "SUM(TOTAL_CASES_ON_TIME + TOTAL_CASES_OVERDUE)"); +// } +// +// public function percentOverdueCasesByUser($userList, $initDate, $endDate) +// { +// $returnList = $this->percentOverdueCasesByUserList($userList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($returnList)); +// } +// +// public function percentOverdueCasesByUserList($userList, $initDate, $endDate, $periodicity) +// { +// return $this->sumCasesListByUser($userList, $initDate, $endDate, $periodicity, "100 * SUM(TOTAL_CASES_OVERDUE)", "SUM(TOTAL_CASES_ON_TIME + TOTAL_CASES_OVERDUE)"); +// } +// +// //new cases +// public function totalNewCasesByProcess($processList, $initDate, $endDate) +// { +// $returnList = $this->totalNewCasesByProcessList($processList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($returnList)); +// } +// +// public function totalNewCasesByProcessList($processList, $initDate, $endDate, $periodicity) +// { +// return $this->sumCasesListByProcess($processList, $initDate, $endDate, $periodicity, "SUM(TOTAL_CASES_IN)", ""); +// } +// +// public function totalNewCasesByUser($userList, $initDate, $endDate) +// { +// $returnList = $this->totalNewCasesByUserList($userList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($returnList)); +// } +// +// public function totalNewCasesByUserList($userList, $initDate, $endDate, $periodicity) +// { +// return $this->sumCasesListByUser($userList, $initDate, $endDate, $periodicity, "SUM(TOTAL_CASES_IN)", ""); +// } +// +// +// //completed cases +// public function totalCompletedCasesByProcess($processList, $initDate, $endDate) +// { +// $returnList = $this->totalCompletedCasesByProcessList($processList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($returnList)); +// } +// +// public function totalCompletedCasesByProcessList($processList, $initDate, $endDate, $periodicity) +// { +// return $this->sumCasesListByProcess($processList, $initDate, $endDate, $periodicity, "SUM(TOTAL_CASES_OUT)", ""); +// } +// +// public function totalCompletedCasesByUser($userList, $initDate, $endDate) +// { +// $returnList = $this->totalCompletedCasesByUserList($userList, $initDate, $endDate, ReportingPeriodicityEnum::NONE); +// return current(reset($returnList)); +// } +// +// public function totalCompletedCasesByUserList($userList, $initDate, $endDate, $periodicity) +// { +// return $this->sumCasesListByUser($userList, $initDate, $endDate, $periodicity, "SUM(TOTAL_CASES_OUT)", ""); +// } +// +// public function sumCasesListByProcess($processList, $initDate, $endDate, $periodicity, $fieldToProcess, $fieldToCompare) +// { +// if ($processList != null && !is_array($processList)) throw new InvalidArgumentException ('employeeList parameter must be an Array or null value.', 0); +// if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); +// if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); +// +// $periodicitySelectFields = $this->periodicityFieldsForSelect($periodicity); +// $periodicityGroup = $this->periodicityFieldsForGrouping($periodicity); +// $initYear = $initDate->format("Y"); +// $initMonth = $initDate->format("m"); +// $initDay = $endDay = 1; +// $endYear = $endDate->format("Y"); +// $endMonth = $endDate->format("m"); +// +// +// $userCondition = ""; +// if ($processList != null && sizeof($processList) > 0) { +// $userCondition = " AND PRO_UID IN " . "('" . implode("','", $processList) . "')"; +// } +// $comparationOperation = ""; +// if (strlen($fieldToCompare) > 0) { +// $comparationOperation = "/$fieldToCompare"; +// } +// +// $sqlString = "SELECT $periodicitySelectFields $fieldToProcess$comparationOperation as Indicator +// FROM PRO_REPORTING +// WHERE +// IF (`YEAR` = $initYear, `MONTH`, `YEAR`) >= IF (`YEAR` = $initYear, $initMonth, $initYear) +// AND +// IF(`YEAR` = $endYear, `MONTH`, `YEAR`) <= IF (`YEAR` = $endYear, $endMonth, $endYear)" +// . $userCondition +// . $periodicityGroup; +// +// $retval = $this->propelExecutor($sqlString); +// return $retval; +// } +// +// public function sumCasesListByUser($processList, $initDate, $endDate, $periodicity, $fieldToProcess, $fieldToCompare) +// { +// if ($processList != null && !is_array($processList)) throw new InvalidArgumentException ('employeeList parameter must be an Array or null value.', 0); +// if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); +// if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); +// +// $periodicitySelectFields = $this->periodicityFieldsForSelect($periodicity); +// $periodicityGroup = $this->periodicityFieldsForGrouping($periodicity); +// $initYear = $initDate->format("Y"); +// $initMonth = $initDate->format("m"); +// $initDay = $endDay = 1; +// $endYear = $endDate->format("Y"); +// $endMonth = $endDate->format("m"); +// +// $userCondition = ""; +// if ($processList != null && sizeof($processList) > 0) { +// $userCondition = " AND USR_UID IN " . "('" . implode("','", $processList) . "')"; +// } +// +// $comparationOperation = ""; +// if (strlen($fieldToCompare) > 0) { +// $comparationOperation = "/" . $fieldToCompare; +// } +// +// $sqlString = "SELECT $periodicitySelectFields $fieldToProcess$comparationOperation as Indicator +// FROM USR_REPORTING +// WHERE +// IF (`YEAR` = $initYear, `MONTH`, `YEAR`) >= IF (`YEAR` = $initYear, $initMonth, $initYear) +// AND +// IF(`YEAR` = $endYear, `MONTH`, `YEAR`) <= IF (`YEAR` = $endYear, $endMonth, $endYear)" +// . $userCondition +// . $periodicityGroup; +// +// $retval = $this->propelExecutor($sqlString); +// return $retval; +// } + + public function peiTasks($processList, $initDate, $endDate, $language) + { + $processCondition = ""; + if ($processList != null && sizeof($processList) > 0) { + $processCondition = " WHERE PRO_UID IN " . "('" . implode("','", $processList) . "')"; + } + //TODO add dates condition in query + $sqlString = " select + i.TAS_UID as uid, + t.CON_VALUE as name, + i.efficienceIndex, + i.averageTime, + i.deviationTime, + i.configuredTime + FROM + ( select + TAS_UID, + $this->peiFormula as efficienceIndex, + AVG(AVG_TIME) as averageTime, + AVG(SDV_TIME) as deviationTime, + CONFIGURED_TASK_TIME as configuredTime + from USR_REPORTING + $processCondition + group by TAS_UID + ) i + left join (select * + from CONTENT + where CON_CATEGORY = 'TAS_TITLE' + and CON_LANG = '$language' + ) t on i.TAS_UID = t.CON_ID"; + $retval = $this->propelExecutor($sqlString); + return $retval; + } + +// public function employeeTasksInfoList($userList, $initDate, $endDate, $language) +// { +// $userCondition = ""; +// if ($userList != null && sizeof($userList) > 0) { +// $userCondition = " WHERE USR_UID IN " . "('" . implode("','", $userList) . "')"; +// } +// //TODO add dates contidion to query +// $sqlString = " select +// i.PRO_UID as ProcessId, +// tp.CON_VALUE as ProcessTitle, +// i.TAS_UID as TaskId, +// tt.CON_VALUE as TaskTitle, +// i.EfficienceIndex, +// i.TimeAverage, +// i.TimeSdv, +// i.CONFIGURED_TASK_TIME as ConfiguredTime +// FROM +// ( select +// PRO_UID, +// TAS_UID, +// (AVG(CONFIGURED_TASK_TIME) + AVG(SDV_TIME))/ AVG(AVG_TIME) as EfficienceIndex, +// AVG(AVG_TIME) as TimeAverage, +// AVG(SDV_TIME) as TimeSdv, +// CONFIGURED_TASK_TIME +// from USR_REPORTING +// $userCondition +// group by PRO_UID, TAS_UID +// ) i +// left join (select * +// from CONTENT +// where CON_CATEGORY = 'TAS_TITLE' +// and CON_LANG = '$language' +// ) tt on i.TAS_UID = tt.CON_ID +// left join (select * +// from CONTENT +// where CON_CATEGORY = 'PRO_TITLE' +// and CON_LANG = '$language' +// ) tp on i.PRO_UID = tp.CON_ID"; +// $retval = $this->propelExecutor($sqlString); +// return $retval; +// } + + private function periodicityFieldsForSelect($periodicity) { + $periodicityFields = $this->periodicityFieldsString($periodicity); + //add a comma if there are periodicity fields + return $periodicityFields + . ((strlen($periodicityFields) > 0) + ? ", " + : ""); + } + + private function periodicityFieldsForGrouping($periodicity) { + $periodicityFields = $this->periodicityFieldsString($periodicity); + + return ((strlen($periodicityFields) > 0) + ? " GROUP BY " + : "") . str_replace(" AS QUARTER", "", str_replace(" AS SEMESTER", "", $periodicityFields)); + } + + private function periodicityFieldsString($periodicity) { + if (!ReportingPeriodicityEnum::isValidValue($periodicity)) throw new ArgumentException('Not supported periodicity: ', 0, 'periodicity'); + + $retval = ""; + switch ($periodicity) { + case ReportingPeriodicityEnum::MONTH; + $retval = "`YEAR`, `MONTH` "; + break; + case ReportingPeriodicityEnum::SEMESTER; + $retval = "`YEAR`, IF (`MONTH` <= 6, 1, 2) AS SEMESTER"; + break; + case ReportingPeriodicityEnum::QUARTER; + $retval = "`YEAR`, CASE WHEN `MONTH` BETWEEN 1 AND 3 THEN 1 WHEN `MONTH` BETWEEN 4 AND 6 THEN 2 WHEN `MONTH` BETWEEN 7 AND 9 THEN 3 WHEN `MONTH` BETWEEN 10 AND 12 THEN 4 END AS QUARTER"; + break; + case ReportingPeriodicityEnum::YEAR; + $retval = "`YEAR` "; + break; + } + return $retval; + } + + private function propelExecutor($sqlString) { + $con = Propel::getConnection(self::$connectionName); + $qry = $con->PrepareStatement($sqlString); + try { + $dataSet = $qry->executeQuery(); + } catch (Exception $e) { + throw new Exception("Can't execute query " . $sqlString); + } + + $rows = Array(); + while ($dataSet->next()) { + $rows[] = $dataSet->getRow(); + } + return $rows; + } + + private function indicatorsBasicQueryBuilder($reportingTable, $filterId, $periodicity, $initDate, $endDate, $fields ) { + if (!is_a($initDate, 'DateTime')) throw new InvalidArgumentException ('initDate parameter must be a DateTime object.', 0); + if (!is_a($endDate, 'DateTime')) throw new InvalidArgumentException ('endDate parameter must be a DateTime object.', 0); + + $tableMetadata = $this->metadataForTable($reportingTable); + $periodicitySelectFields = $this->periodicityFieldsForSelect($periodicity); + $periodicityGroup = $this->periodicityFieldsForGrouping($periodicity); + $initYear = $initDate->format("Y"); + $initMonth = $initDate->format("m"); + $endYear = $endDate->format("Y"); + $endMonth = $endDate->format("m"); + + $filterCondition = ""; + if ($filterId != null && $filterId > 0) { + $filterCondition = " AND ".$tableMetadata["keyField"]." = '$filterId'"; + } + + $sqlString = "SELECT $periodicitySelectFields $fields + FROM ".$tableMetadata["tableName"]. + " WHERE + IF (`YEAR` = $initYear, `MONTH`, `YEAR`) >= IF (`YEAR` = $initYear, $initMonth, $initYear) + AND + IF(`YEAR` = $endYear, `MONTH`, `YEAR`) <= IF (`YEAR` = $endYear, $endMonth, $endYear)" + . $filterCondition + . $periodicityGroup; + return $sqlString; + } + + private function metadataForTable($table) { + $returnVal = null; + switch (strtolower($table)) { + case IndicatorDataSourcesEnum::USER: + $returnVal = $this->userReportingMetadata; + break; + case IndicatorDataSourcesEnum::PROCESS: + $returnVal = $this->processReportingMetadata; + break; + case IndicatorDataSourcesEnum::USER_GROUP: + $returnVal = $this->userGroupReportingMetadata; + break; + case IndicatorDataSourcesEnum::PROCESS_CATEGORY: + $returnVal = $this->processCategoryReportingMetadata; + break; + } + if ($returnVal == null) { + throw new Exception("'$table' it's not supportes. It has not associated a template."); + } + return $returnVal; + } +} + + diff --git a/workflow/engine/classes/model/Catalog.php b/workflow/engine/classes/model/Catalog.php new file mode 100644 index 000000000..38fa398d3 --- /dev/null +++ b/workflow/engine/classes/model/Catalog.php @@ -0,0 +1,111 @@ +toArray(BasePeer::TYPE_FIELDNAME); + $catalog->fromArray( $fields, BasePeer::TYPE_FIELDNAME ); + return $fields; + } catch (Exception $error) { + throw $error; + } + } + + public function createOrUpdate($data) + { + $connection = Propel::getConnection(CatalogPeer::DATABASE_NAME); + try { + if (!isset($data['CAT_UID'])) { + $data['CAT_CREATE_DATE'] = date('Y-m-d H:i:s'); + $msg = "Create Catalog"; + $catalog = new catalog(); + } else { + $msg = "Update Catalog"; + $catalog = CatalogPeer::retrieveByPK($data['CAT_UID']); + } + $data['CAT_UPDATE_DATE'] = date('Y-m-d H:i:s'); + $catalog->fromArray($data, BasePeer::TYPE_FIELDNAME); + if ($catalog->validate()) { + $connection->begin(); + $result = $catalog->save(); + $connection->commit(); + + G::auditLog($msg, "Catalog ID Label: ".$catalog->getCatLabelId()." Catalog type: (".$catalog->getCatType().") "); + return $catalog->getCatLabelId(); + } else { + $message = ''; + $validationFailures = $catalog->getValidationFailures(); + foreach ($validationFailures as $validationFailure) { + $message .= $validationFailure->getMessage() . '. '; + } + throw(new Exception(G::LoadTranslation("ID_RECORD_CANNOT_BE_CREATED", SYS_LANG) . ' ' . $message)); + } + } catch (Exception $error) { + $connection->rollback(); + throw $error; + } + } + + public function remove($catUid, $catType) + { + $connection = Propel::getConnection(CatalogPeer::DATABASE_NAME); + try { + $catalog = CatalogPeer::retrieveByPK($catUid, $catType); + if (!is_null($catalog)) { + $connection->begin(); + $catalogData = $this->load($dasUid); + $result = $catalog->delete(); + $connection->commit(); + + G::auditLog("Deletecatalog", "Catalog Id Label: ". $catalogData['CAT_UID']." Catalog Type: (". $catalogData['CAT_TYPE'] .") "); + return $result; + } else { + throw new Exception('Error trying to delete: The row "' . $catalogData['CAT_UID']. '" does not exist.'); + } + } catch (Exception $error) { + $connection->rollback(); + throw $error; + } + } + + public function loadByType ($catType) + { + try { + $criteria = new Criteria(); + $criteria->clearSelectColumns(); + $criteria->add(CatalogPeer::CAT_TYPE, strtoupper($catType), Criteria::EQUAL); + + $rs = CatalogPeer::doSelectRS($criteria); + $rs->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $catalog = array(); + + while ($rs->next()) { + $row = $rs->getRow(); + $row['CAT_LABEL_ID'] = G::loadTranslation($row['CAT_LABEL_ID']); + $catalog[] = $row; + } + + return $catalog; + } catch (Exception $error) { + throw $error; + } + } +} + diff --git a/workflow/engine/classes/model/CatalogPeer.php b/workflow/engine/classes/model/CatalogPeer.php new file mode 100644 index 000000000..f7537e274 --- /dev/null +++ b/workflow/engine/classes/model/CatalogPeer.php @@ -0,0 +1,23 @@ +toArray(BasePeer::TYPE_FIELDNAME); + $dashboard->fromArray( $fields, BasePeer::TYPE_FIELDNAME ); + return $fields; + } catch (Exception $error) { + throw $error; + } + } + + public function createOrUpdate($data) + { + $connection = Propel::getConnection(DashboardPeer::DATABASE_NAME); + try { + + if (!isset($data['DAS_UID'])) { + $data['DAS_UID'] = G::generateUniqueID(); + $data['DAS_CREATE_DATE'] = date('Y-m-d H:i:s'); + $dashboard = new Dashboard(); + $msg = 'Create '; + } else { + $msg = 'Update '; + $dashboard = DashboardPeer::retrieveByPK($data['DAS_UID']); + } + + $data['DAS_UPDATE_DATE'] = date('Y-m-d H:i:s'); + $dashboard->fromArray($data, BasePeer::TYPE_FIELDNAME); + if ($dashboard->validate()) { + $connection->begin(); + $result = $dashboard->save(); + $connection->commit(); + + G::auditLog($msg, "Dashboard Name: " . $dashboard->getDasTitle() . " Dashboard ID: (".$dashboard->getDasUid().") "); + return $dashboard->getDasUid(); + } else { + $message = ''; + $validationFailures = $dashboard->getValidationFailures(); + foreach ($validationFailures as $validationFailure) { + $message .= $validationFailure->getMessage() . '. '; + } + throw(new Exception(G::LoadTranslation("ID_RECORD_CANNOT_BE_CREATED", SYS_LANG) . ' ' . $message)); + } + } catch (Exception $error) { + $connection->rollback(); + throw $error; + } + } + + public function remove($dasUid) + { + $connection = Propel::getConnection(DashboardPeer::DATABASE_NAME); + try { + + require_once 'classes/model/DashboardDasInd.php'; + $criteria = new Criteria('workflow'); + $criteria->add(DashboardDasIndPeer::DAS_UID, $dasUid); + DashboardDasIndPeer::doDelete($criteria); + + require_once 'classes/model/DashboardIndicator.php'; + $criteria = new Criteria('workflow'); + $criteria->add(DashboardIndicatorPeer::DAS_UID, $dasUid); + DashboardIndicatorPeer::doDelete($criteria); + + $dashboard = DashboardPeer::retrieveByPK($dasUid); + if (!is_null($dashboard)) { + $connection->begin(); + $dashboardData = $this->load($dasUid); + $result = $dashboard->delete(); + $connection->commit(); + + G::auditLog("Deletedashboard", "Dashboard Name: ". $dashboardData['DAS_TITLE']." Dashboard ID: (".$dasUid.") "); + return $result; + } else { + throw new Exception('Error trying to delete: The row "' . $dasUid. '" does not exist.'); + } + } catch (Exception $error) { + $connection->rollback(); + throw $error; + } + } +} + diff --git a/workflow/engine/classes/model/DashboardDasInd.php b/workflow/engine/classes/model/DashboardDasInd.php new file mode 100644 index 000000000..d6796bfa0 --- /dev/null +++ b/workflow/engine/classes/model/DashboardDasInd.php @@ -0,0 +1,117 @@ +add(DashboardDasIndPeer::DAS_UID, $dasUid); + + $dataset = DashboardDasIndPeer::doSelectRS($criteria); + $dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $fields = array(); + + while ($dataset->next()) { + $auxField = $dataset->getRow(); + $fields[] = $auxField; + } + + return $fields; + } catch (Exception $error) { + throw $error; + } + } + + public function loadByOwner ($ownerUid) + { + try { + + $criteria = new Criteria('workflow'); + $criteria->add(DashboardDasIndPeer::OWNER_UID, $ownerUid); + + $dataset = DashboardDasIndPeer::doSelectRS($criteria); + $dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $fields = array(); + + while ($dataset->next()) { + $auxField = $dataset->getRow(); + $fields[] = $auxField; + } + + return $fields; + } catch (Exception $error) { + throw $error; + } + } + + public function create($data) + { + $connection = Propel::getConnection(DashboardDasIndPeer::DATABASE_NAME); + try { + $dashboardDasInd = new DashboardDasInd(); + $dashboardDasInd->fromArray($data, BasePeer::TYPE_FIELDNAME); + if ($dashboardDasInd->validate()) { + $connection->begin(); + $result = $dashboardDasInd->save(); + $connection->commit(); + + G::auditLog("Create", "Dashboard Owner: ". $data['OWNER_UID']." Dashboard ID: (".$dashboardDasInd->getDasUid().") "); + return $dashboardDasInd; + } else { + $message = ''; + $validationFailures = $dashboardDasInd->getValidationFailures(); + foreach ($validationFailures as $validationFailure) { + $message .= $validationFailure->getMessage() . '. '; + } + throw(new Exception(G::LoadTranslation("ID_RECORD_CANNOT_BE_CREATED", SYS_LANG) . ' ' . $message)); + } + } catch (Exception $error) { + $connection->rollback(); + throw $error; + } + } + + public function remove($dasUid, $owner) + { + $connection = Propel::getConnection(DashboardDasIndPeer::DATABASE_NAME); + try { + $dashboardDasInd = DashboardDasIndPeer::retrieveByPK($dasUid, $owner); + if (!is_null($dashboardDasInd)) { + $connection->begin(); + $result = $dashboardDasInd->delete(); + $connection->commit(); + + G::auditLog("DeletedashboardIndicator", "Dashboard ID: ". $dasUid ." Dashboard owner ID: (".$owner.") "); + return $result; + } else { + throw new Exception('Error trying to delete: The row "' . $dasUid. '" does not exist.'); + } + } catch (Exception $error) { + $connection->rollback(); + throw $error; + } + } + + public function getOwnerByDashboard ($dasUid) + { + + } + +} + diff --git a/workflow/engine/classes/model/DashboardDasIndPeer.php b/workflow/engine/classes/model/DashboardDasIndPeer.php new file mode 100644 index 000000000..ba51a0ce4 --- /dev/null +++ b/workflow/engine/classes/model/DashboardDasIndPeer.php @@ -0,0 +1,23 @@ +toArray(BasePeer::TYPE_FIELDNAME); + $dashboardIndicator->fromArray( $fields, BasePeer::TYPE_FIELDNAME ); + return $fields; + } catch (Exception $error) { + throw $error; + } + } + function loadbyDasUid ($dasUid, $vmeasureDate, $vcompareDate, $userUid) + { + G::loadClass('indicatorsCalculator'); + $calculator = new \IndicatorsCalculator(); + + try { + + $connection = Propel::getConnection('workflow'); + $qryString = "select * from CONFIGURATION where CFG_UID = 'DASHBOARDS_SETTINGS' and USR_UID = '$userUid'"; + $qry = $connection->PrepareStatement($qryString); + $dataSet = $qry->executeQuery(); + $dashConfig = array(); + while ($dataSet->next()){ + $row = $dataSet->getRow(); + $dashConfig = unserialize($row['CFG_VALUE']); + } + + $criteria = new Criteria( 'workflow' ); + $criteria->clearSelectColumns()->clearOrderByColumns(); + + $criteria->add( DashboardIndicatorPeer::DAS_UID, $dasUid, criteria::EQUAL ); + + $rs = DashboardIndicatorPeer::doSelectRS( $criteria ); + $rs->setFetchmode( ResultSet::FETCHMODE_ASSOC ); + $dashboardIndicator = array(); + while ($rs->next()) { + $row = $rs->getRow(); + + //$currentDate = new DateTime (date("Y-m-d")); + $measureDate = new DateTime ($vmeasureDate); + $compareDate = new DateTime ($vcompareDate); + $uid = ($row['DAS_UID_PROCESS'] == '0' ? null: $row['DAS_UID_PROCESS']) ; + switch ($row['DAS_IND_TYPE']) { + case '1010': + $value = current(reset($calculator->peiHistoric($uid, $measureDate, $measureDate, \ReportingPeriodicityEnum::NONE))); + $oldValue = current(reset($calculator->peiHistoric($uid, $compareDate, $compareDate, \ReportingPeriodicityEnum::NONE))); + $row['DAS_IND_VARIATION'] = $value - $oldValue; + break; + case '1030': + $value = current(reset($calculator->ueiHistoric(null, $measureDate, $measureDate, \ReportingPeriodicityEnum::NONE))); + $oldValue = current(reset($calculator->ueiHistoric($uid, $compareDate, $compareDate, \ReportingPeriodicityEnum::NONE))); + $row['DAS_IND_VARIATION'] = $value - $oldValue; + break; + default: + $arrResult = $calculator->generalIndicatorData($row['DAS_IND_UID'], $measureDate, $measureDate, \ReportingPeriodicityEnum::NONE); + $value = $arrResult[0]['value']; + $row['DAS_IND_VARIATION'] = $row['DAS_IND_GOAL']; + break; + } + $row['DAS_IND_VALUE'] = $value; + + $indId = $row['DAS_IND_UID']; + $row['DAS_IND_X'] = 0; + $row['DAS_IND_Y'] = 0; + $row['DAS_IND_WIDTH'] = 0; + $row['DAS_IND_HEIGHT'] = 0; + $row['DAS_IND_FAVORITE'] = 0; + + foreach ($dashConfig as $dashId=>$oneDash) { + if($dashId == $dasUid && is_array($oneDash['dashData'])) { + foreach($oneDash['dashData'] as $graphConfig) { + if ($graphConfig['indicatorId'] == $indId) { + $row['DAS_IND_X'] = $graphConfig['x']; + $row['DAS_IND_Y'] = $graphConfig['y']; + $row['DAS_IND_WIDTH'] = $graphConfig['width']; + $row['DAS_IND_HEIGHT'] = $graphConfig['height']; + } + } + } + } + + $dashboardIndicator[] = $row; + } + return $dashboardIndicator; + } catch (Exception $error) { + throw $error; + } + } + + + + public function createOrUpdate($data) + { + $connection = Propel::getConnection(DashboardIndicatorPeer::DATABASE_NAME); + try { + if (!isset($data['DAS_IND_UID'])) { + $data['DAS_IND_UID'] = G::generateUniqueID(); + $data['DAS_IND_CREATE_DATE'] = date('Y-m-d H:i:s'); + $dashboardIndicator = new DashboardIndicator(); + $msg = 'Create'; + } else { + $msg = 'Update'; + $dashboardIndicator = DashboardIndicatorPeer::retrieveByPK($data['DAS_IND_UID']); + } + $data['DAS_IND_UPDATE_DATE'] = date('Y-m-d H:i:s'); + $dashboardIndicator->fromArray($data, BasePeer::TYPE_FIELDNAME); + if ($dashboardIndicator->validate()) { + $connection->begin(); + $result = $dashboardIndicator->save(); + $connection->commit(); + + G::auditLog($msg, "Dashboard Indicator Name: ".$dashboardIndicator->getDasIndTitle()." Dashboard indicator ID: (".$dashboardIndicator->getDasIndUid() .") "); + return $dashboardIndicator->getDasIndUid(); + } else { + $message = ''; + $validationFailures = $dashboardIndicator->getValidationFailures(); + foreach ($validationFailures as $validationFailure) { + $message .= $validationFailure->getMessage() . '. '; + } + throw(new Exception(G::LoadTranslation("ID_RECORD_CANNOT_BE_CREATED", SYS_LANG) . ' ' . $message)); + } + } catch (Exception $error) { + $connection->rollback(); + throw $error; + } + } + + public function remove($dasIndUid) + { + $connection = Propel::getConnection(DashboardIndicatorPeer::DATABASE_NAME); + try { + $dashboardIndicator = DashboardIndicatorPeer::retrieveByPK($dasIndUid); + if (!is_null($dashboardIndicator)) { + $connection->begin(); + $dashboardIndicatorData = $this->load($dasIndUid); + $result = $dashboardIndicator->delete(); + $connection->commit(); + + G::auditLog("DeletedashboardIndicator", "Dashboard Indicator Name: ". $dashboardIndicatorData['DAS_IND_TITLE']." Dashboard Instance ID: (".$dasIndUid.") "); + return $result; + } else { + throw new Exception('Error trying to delete: The row "' . $dasIndUid. '" does not exist.'); + } + } catch (Exception $error) { + $connection->rollback(); + throw $error; + } + } +} + diff --git a/workflow/engine/classes/model/DashboardIndicatorPeer.php b/workflow/engine/classes/model/DashboardIndicatorPeer.php new file mode 100644 index 000000000..c438616b5 --- /dev/null +++ b/workflow/engine/classes/model/DashboardIndicatorPeer.php @@ -0,0 +1,23 @@ +dbMap !== null); + } + + /** + * Gets the databasemap this map builder built. + * + * @return the databasemap + */ + public function getDatabaseMap() + { + return $this->dbMap; + } + + /** + * The doBuild() method builds the DatabaseMap + * + * @return void + * @throws PropelException + */ + public function doBuild() + { + $this->dbMap = Propel::getDatabaseMap('workflow'); + + $tMap = $this->dbMap->addTable('CATALOG'); + $tMap->setPhpName('Catalog'); + + $tMap->setUseIdGenerator(false); + + $tMap->addPrimaryKey('CAT_UID', 'CatUid', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addColumn('CAT_LABEL_ID', 'CatLabelId', 'string', CreoleTypes::VARCHAR, true, 100); + + $tMap->addPrimaryKey('CAT_TYPE', 'CatType', 'string', CreoleTypes::VARCHAR, true, 100); + + $tMap->addColumn('CAT_FLAG', 'CatFlag', 'string', CreoleTypes::VARCHAR, false, 50); + + $tMap->addColumn('CAT_OBSERVATION', 'CatObservation', 'string', CreoleTypes::LONGVARCHAR, false, null); + + $tMap->addColumn('CAT_CREATE_DATE', 'CatCreateDate', 'int', CreoleTypes::TIMESTAMP, true, null); + + $tMap->addColumn('CAT_UPDATE_DATE', 'CatUpdateDate', 'int', CreoleTypes::TIMESTAMP, false, null); + + } // doBuild() + +} // CatalogMapBuilder diff --git a/workflow/engine/classes/model/map/DashboardDasIndMapBuilder.php b/workflow/engine/classes/model/map/DashboardDasIndMapBuilder.php new file mode 100644 index 000000000..bca2c9ee8 --- /dev/null +++ b/workflow/engine/classes/model/map/DashboardDasIndMapBuilder.php @@ -0,0 +1,76 @@ +dbMap !== null); + } + + /** + * Gets the databasemap this map builder built. + * + * @return the databasemap + */ + public function getDatabaseMap() + { + return $this->dbMap; + } + + /** + * The doBuild() method builds the DatabaseMap + * + * @return void + * @throws PropelException + */ + public function doBuild() + { + $this->dbMap = Propel::getDatabaseMap('workflow'); + + $tMap = $this->dbMap->addTable('DASHBOARD_DAS_IND'); + $tMap->setPhpName('DashboardDasInd'); + + $tMap->setUseIdGenerator(false); + + $tMap->addForeignPrimaryKey('DAS_UID', 'DasUid', 'string' , CreoleTypes::VARCHAR, 'DASHBOARD', 'DAS_UID', true, 32); + + $tMap->addPrimaryKey('OWNER_UID', 'OwnerUid', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addColumn('OWNER_TYPE', 'OwnerType', 'string', CreoleTypes::VARCHAR, true, 15); + + } // doBuild() + +} // DashboardDasIndMapBuilder diff --git a/workflow/engine/classes/model/map/DashboardIndicatorMapBuilder.php b/workflow/engine/classes/model/map/DashboardIndicatorMapBuilder.php new file mode 100644 index 000000000..d62ae2635 --- /dev/null +++ b/workflow/engine/classes/model/map/DashboardIndicatorMapBuilder.php @@ -0,0 +1,98 @@ +dbMap !== null); + } + + /** + * Gets the databasemap this map builder built. + * + * @return the databasemap + */ + public function getDatabaseMap() + { + return $this->dbMap; + } + + /** + * The doBuild() method builds the DatabaseMap + * + * @return void + * @throws PropelException + */ + public function doBuild() + { + $this->dbMap = Propel::getDatabaseMap('workflow'); + + $tMap = $this->dbMap->addTable('DASHBOARD_INDICATOR'); + $tMap->setPhpName('DashboardIndicator'); + + $tMap->setUseIdGenerator(false); + + $tMap->addPrimaryKey('DAS_IND_UID', 'DasIndUid', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addForeignKey('DAS_UID', 'DasUid', 'string', CreoleTypes::VARCHAR, 'DASHBOARD', 'DAS_UID', true, 32); + + $tMap->addColumn('DAS_IND_TYPE', 'DasIndType', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addColumn('DAS_IND_TITLE', 'DasIndTitle', 'string', CreoleTypes::VARCHAR, true, 255); + + $tMap->addColumn('DAS_IND_GOAL', 'DasIndGoal', 'double', CreoleTypes::DECIMAL, true, 7,2); + + $tMap->addColumn('DAS_IND_DIRECTION', 'DasIndDirection', 'int', CreoleTypes::TINYINT, true, null); + + $tMap->addColumn('DAS_UID_PROCESS', 'DasUidProcess', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addColumn('DAS_IND_FIRST_FIGURE', 'DasIndFirstFigure', 'string', CreoleTypes::VARCHAR, false, 32); + + $tMap->addColumn('DAS_IND_FIRST_FREQUENCY', 'DasIndFirstFrequency', 'string', CreoleTypes::VARCHAR, false, 32); + + $tMap->addColumn('DAS_IND_SECOND_FIGURE', 'DasIndSecondFigure', 'string', CreoleTypes::VARCHAR, false, 32); + + $tMap->addColumn('DAS_IND_SECOND_FREQUENCY', 'DasIndSecondFrequency', 'string', CreoleTypes::VARCHAR, false, 32); + + $tMap->addColumn('DAS_IND_CREATE_DATE', 'DasIndCreateDate', 'int', CreoleTypes::TIMESTAMP, true, null); + + $tMap->addColumn('DAS_IND_UPDATE_DATE', 'DasIndUpdateDate', 'int', CreoleTypes::TIMESTAMP, false, null); + + $tMap->addColumn('DAS_IND_STATUS', 'DasIndStatus', 'int', CreoleTypes::TINYINT, true, null); + + } // doBuild() + +} // DashboardIndicatorMapBuilder diff --git a/workflow/engine/classes/model/map/DashboardMapBuilder.php b/workflow/engine/classes/model/map/DashboardMapBuilder.php new file mode 100644 index 000000000..328cb3417 --- /dev/null +++ b/workflow/engine/classes/model/map/DashboardMapBuilder.php @@ -0,0 +1,82 @@ +dbMap !== null); + } + + /** + * Gets the databasemap this map builder built. + * + * @return the databasemap + */ + public function getDatabaseMap() + { + return $this->dbMap; + } + + /** + * The doBuild() method builds the DatabaseMap + * + * @return void + * @throws PropelException + */ + public function doBuild() + { + $this->dbMap = Propel::getDatabaseMap('workflow'); + + $tMap = $this->dbMap->addTable('DASHBOARD'); + $tMap->setPhpName('Dashboard'); + + $tMap->setUseIdGenerator(false); + + $tMap->addPrimaryKey('DAS_UID', 'DasUid', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addColumn('DAS_TITLE', 'DasTitle', 'string', CreoleTypes::VARCHAR, true, 255); + + $tMap->addColumn('DAS_DESCRIPTION', 'DasDescription', 'string', CreoleTypes::LONGVARCHAR, false, null); + + $tMap->addColumn('DAS_CREATE_DATE', 'DasCreateDate', 'int', CreoleTypes::TIMESTAMP, true, null); + + $tMap->addColumn('DAS_UPDATE_DATE', 'DasUpdateDate', 'int', CreoleTypes::TIMESTAMP, false, null); + + $tMap->addColumn('DAS_STATUS', 'DasStatus', 'int', CreoleTypes::TINYINT, true, null); + + } // doBuild() + +} // DashboardMapBuilder diff --git a/workflow/engine/classes/model/map/ProReportingMapBuilder.php b/workflow/engine/classes/model/map/ProReportingMapBuilder.php new file mode 100644 index 000000000..623480af9 --- /dev/null +++ b/workflow/engine/classes/model/map/ProReportingMapBuilder.php @@ -0,0 +1,94 @@ +dbMap !== null); + } + + /** + * Gets the databasemap this map builder built. + * + * @return the databasemap + */ + public function getDatabaseMap() + { + return $this->dbMap; + } + + /** + * The doBuild() method builds the DatabaseMap + * + * @return void + * @throws PropelException + */ + public function doBuild() + { + $this->dbMap = Propel::getDatabaseMap('workflow'); + + $tMap = $this->dbMap->addTable('PRO_REPORTING'); + $tMap->setPhpName('ProReporting'); + + $tMap->setUseIdGenerator(false); + + $tMap->addPrimaryKey('PRO_UID', 'ProUid', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addPrimaryKey('MONTH', 'Month', 'int', CreoleTypes::INTEGER, true, null); + + $tMap->addPrimaryKey('YEAR', 'Year', 'int', CreoleTypes::INTEGER, true, null); + + $tMap->addColumn('AVG_TIME', 'AvgTime', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('SDV_TIME', 'SdvTime', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_IN', 'TotalCasesIn', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_OUT', 'TotalCasesOut', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('CONFIGURED_PROCESS_TIME', 'ConfiguredProcessTime', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('CONFIGURED_PROCESS_COST', 'ConfiguredProcessCost', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_OPEN', 'TotalCasesOpen', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_OVERDUE', 'TotalCasesOverdue', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_ON_TIME', 'TotalCasesOnTime', 'double', CreoleTypes::DECIMAL, false, 7,2); + + } // doBuild() + +} // ProReportingMapBuilder diff --git a/workflow/engine/classes/model/map/UsrReportingMapBuilder.php b/workflow/engine/classes/model/map/UsrReportingMapBuilder.php new file mode 100644 index 000000000..46e35d9c3 --- /dev/null +++ b/workflow/engine/classes/model/map/UsrReportingMapBuilder.php @@ -0,0 +1,98 @@ +dbMap !== null); + } + + /** + * Gets the databasemap this map builder built. + * + * @return the databasemap + */ + public function getDatabaseMap() + { + return $this->dbMap; + } + + /** + * The doBuild() method builds the DatabaseMap + * + * @return void + * @throws PropelException + */ + public function doBuild() + { + $this->dbMap = Propel::getDatabaseMap('workflow'); + + $tMap = $this->dbMap->addTable('USR_REPORTING'); + $tMap->setPhpName('UsrReporting'); + + $tMap->setUseIdGenerator(false); + + $tMap->addPrimaryKey('USR_UID', 'UsrUid', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addPrimaryKey('TAS_UID', 'TasUid', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addColumn('PRO_UID', 'ProUid', 'string', CreoleTypes::VARCHAR, true, 32); + + $tMap->addPrimaryKey('MONTH', 'Month', 'int', CreoleTypes::INTEGER, true, null); + + $tMap->addPrimaryKey('YEAR', 'Year', 'int', CreoleTypes::INTEGER, true, null); + + $tMap->addColumn('TOTAL_TIME_BY_TASK', 'TotalTimeByTask', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_IN', 'TotalCasesIn', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_OUT', 'TotalCasesOut', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('USER_HOUR_COST', 'UserHourCost', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('AVG_TIME', 'AvgTime', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('SDV_TIME', 'SdvTime', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('CONFIGURED_TASK_TIME', 'ConfiguredTaskTime', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_OVERDUE', 'TotalCasesOverdue', 'double', CreoleTypes::DECIMAL, false, 7,2); + + $tMap->addColumn('TOTAL_CASES_ON_TIME', 'TotalCasesOnTime', 'double', CreoleTypes::DECIMAL, false, 7,2); + + } // doBuild() + +} // UsrReportingMapBuilder diff --git a/workflow/engine/classes/model/om/BaseCatalog.php b/workflow/engine/classes/model/om/BaseCatalog.php new file mode 100644 index 000000000..be4eb78b3 --- /dev/null +++ b/workflow/engine/classes/model/om/BaseCatalog.php @@ -0,0 +1,926 @@ +cat_uid; + } + + /** + * Get the [cat_label_id] column value. + * + * @return string + */ + public function getCatLabelId() + { + + return $this->cat_label_id; + } + + /** + * Get the [cat_type] column value. + * + * @return string + */ + public function getCatType() + { + + return $this->cat_type; + } + + /** + * Get the [cat_flag] column value. + * + * @return string + */ + public function getCatFlag() + { + + return $this->cat_flag; + } + + /** + * Get the [cat_observation] column value. + * + * @return string + */ + public function getCatObservation() + { + + return $this->cat_observation; + } + + /** + * Get the [optionally formatted] [cat_create_date] column value. + * + * @param string $format The date/time format string (either date()-style or strftime()-style). + * If format is NULL, then the integer unix timestamp will be returned. + * @return mixed Formatted date/time value as string or integer unix timestamp (if format is NULL). + * @throws PropelException - if unable to convert the date/time to timestamp. + */ + public function getCatCreateDate($format = 'Y-m-d H:i:s') + { + + if ($this->cat_create_date === null || $this->cat_create_date === '') { + return null; + } elseif (!is_int($this->cat_create_date)) { + // a non-timestamp value was set externally, so we convert it + $ts = strtotime($this->cat_create_date); + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse value of [cat_create_date] as date/time value: " . + var_export($this->cat_create_date, true)); + } + } else { + $ts = $this->cat_create_date; + } + if ($format === null) { + return $ts; + } elseif (strpos($format, '%') !== false) { + return strftime($format, $ts); + } else { + return date($format, $ts); + } + } + + /** + * Get the [optionally formatted] [cat_update_date] column value. + * + * @param string $format The date/time format string (either date()-style or strftime()-style). + * If format is NULL, then the integer unix timestamp will be returned. + * @return mixed Formatted date/time value as string or integer unix timestamp (if format is NULL). + * @throws PropelException - if unable to convert the date/time to timestamp. + */ + public function getCatUpdateDate($format = 'Y-m-d H:i:s') + { + + if ($this->cat_update_date === null || $this->cat_update_date === '') { + return null; + } elseif (!is_int($this->cat_update_date)) { + // a non-timestamp value was set externally, so we convert it + $ts = strtotime($this->cat_update_date); + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse value of [cat_update_date] as date/time value: " . + var_export($this->cat_update_date, true)); + } + } else { + $ts = $this->cat_update_date; + } + if ($format === null) { + return $ts; + } elseif (strpos($format, '%') !== false) { + return strftime($format, $ts); + } else { + return date($format, $ts); + } + } + + /** + * Set the value of [cat_uid] column. + * + * @param string $v new value + * @return void + */ + public function setCatUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->cat_uid !== $v || $v === '0') { + $this->cat_uid = $v; + $this->modifiedColumns[] = CatalogPeer::CAT_UID; + } + + } // setCatUid() + + /** + * Set the value of [cat_label_id] column. + * + * @param string $v new value + * @return void + */ + public function setCatLabelId($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->cat_label_id !== $v || $v === '') { + $this->cat_label_id = $v; + $this->modifiedColumns[] = CatalogPeer::CAT_LABEL_ID; + } + + } // setCatLabelId() + + /** + * Set the value of [cat_type] column. + * + * @param string $v new value + * @return void + */ + public function setCatType($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->cat_type !== $v || $v === '') { + $this->cat_type = $v; + $this->modifiedColumns[] = CatalogPeer::CAT_TYPE; + } + + } // setCatType() + + /** + * Set the value of [cat_flag] column. + * + * @param string $v new value + * @return void + */ + public function setCatFlag($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->cat_flag !== $v || $v === '') { + $this->cat_flag = $v; + $this->modifiedColumns[] = CatalogPeer::CAT_FLAG; + } + + } // setCatFlag() + + /** + * Set the value of [cat_observation] column. + * + * @param string $v new value + * @return void + */ + public function setCatObservation($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->cat_observation !== $v || $v === '') { + $this->cat_observation = $v; + $this->modifiedColumns[] = CatalogPeer::CAT_OBSERVATION; + } + + } // setCatObservation() + + /** + * Set the value of [cat_create_date] column. + * + * @param int $v new value + * @return void + */ + public function setCatCreateDate($v) + { + + if ($v !== null && !is_int($v)) { + $ts = strtotime($v); + //Date/time accepts null values + if ($v == '') { + $ts = null; + } + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse date/time value for [cat_create_date] from input: " . + var_export($v, true)); + } + } else { + $ts = $v; + } + if ($this->cat_create_date !== $ts) { + $this->cat_create_date = $ts; + $this->modifiedColumns[] = CatalogPeer::CAT_CREATE_DATE; + } + + } // setCatCreateDate() + + /** + * Set the value of [cat_update_date] column. + * + * @param int $v new value + * @return void + */ + public function setCatUpdateDate($v) + { + + if ($v !== null && !is_int($v)) { + $ts = strtotime($v); + //Date/time accepts null values + if ($v == '') { + $ts = null; + } + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse date/time value for [cat_update_date] from input: " . + var_export($v, true)); + } + } else { + $ts = $v; + } + if ($this->cat_update_date !== $ts) { + $this->cat_update_date = $ts; + $this->modifiedColumns[] = CatalogPeer::CAT_UPDATE_DATE; + } + + } // setCatUpdateDate() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (1-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param ResultSet $rs The ResultSet class with cursor advanced to desired record pos. + * @param int $startcol 1-based offset column which indicates which restultset column to start with. + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate(ResultSet $rs, $startcol = 1) + { + try { + + $this->cat_uid = $rs->getString($startcol + 0); + + $this->cat_label_id = $rs->getString($startcol + 1); + + $this->cat_type = $rs->getString($startcol + 2); + + $this->cat_flag = $rs->getString($startcol + 3); + + $this->cat_observation = $rs->getString($startcol + 4); + + $this->cat_create_date = $rs->getTimestamp($startcol + 5, null); + + $this->cat_update_date = $rs->getTimestamp($startcol + 6, null); + + $this->resetModified(); + + $this->setNew(false); + + // FIXME - using NUM_COLUMNS may be clearer. + return $startcol + 7; // 7 = CatalogPeer::NUM_COLUMNS - CatalogPeer::NUM_LAZY_LOAD_COLUMNS). + + } catch (Exception $e) { + throw new PropelException("Error populating Catalog object", $e); + } + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param Connection $con + * @return void + * @throws PropelException + * @see BaseObject::setDeleted() + * @see BaseObject::isDeleted() + */ + public function delete($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(CatalogPeer::DATABASE_NAME); + } + + try { + $con->begin(); + CatalogPeer::doDelete($this, $con); + $this->setDeleted(true); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. If the object is new, + * it inserts it; otherwise an update is performed. This method + * wraps the doSave() worker method in a transaction. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update + * @throws PropelException + * @see doSave() + */ + public function save($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(CatalogPeer::DATABASE_NAME); + } + + try { + $con->begin(); + $affectedRows = $this->doSave($con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update and any referring + * @throws PropelException + * @see save() + */ + protected function doSave($con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + + // If this object has been modified, then save it to the database. + if ($this->isModified()) { + if ($this->isNew()) { + $pk = CatalogPeer::doInsert($this, $con); + $affectedRows += 1; // we are assuming that there is only 1 row per doInsert() which + // should always be true here (even though technically + // BasePeer::doInsert() can insert multiple rows). + + $this->setNew(false); + } else { + $affectedRows += CatalogPeer::doUpdate($this, $con); + } + $this->resetModified(); // [HL] After being saved an object is no longer 'modified' + } + + $this->alreadyInSave = false; + } + return $affectedRows; + } // doSave() + + /** + * Array of ValidationFailed objects. + * @var array ValidationFailed[] + */ + protected $validationFailures = array(); + + /** + * Gets any ValidationFailed objects that resulted from last call to validate(). + * + * + * @return array ValidationFailed[] + * @see validate() + */ + public function getValidationFailures() + { + return $this->validationFailures; + } + + /** + * Validates the objects modified field values and all objects related to this table. + * + * If $columns is either a column name or an array of column names + * only those columns are validated. + * + * @param mixed $columns Column name or an array of column names. + * @return boolean Whether all columns pass validation. + * @see doValidate() + * @see getValidationFailures() + */ + public function validate($columns = null) + { + $res = $this->doValidate($columns); + if ($res === true) { + $this->validationFailures = array(); + return true; + } else { + $this->validationFailures = $res; + return false; + } + } + + /** + * This function performs the validation work for complex object models. + * + * In addition to checking the current object, all related objects will + * also be validated. If all pass then true is returned; otherwise + * an aggreagated array of ValidationFailed objects will be returned. + * + * @param array $columns Array of column names to validate. + * @return mixed true if all validations pass; + array of ValidationFailed objects otherwise. + */ + protected function doValidate($columns = null) + { + if (!$this->alreadyInValidation) { + $this->alreadyInValidation = true; + $retval = null; + + $failureMap = array(); + + + if (($retval = CatalogPeer::doValidate($this, $columns)) !== true) { + $failureMap = array_merge($failureMap, $retval); + } + + + + $this->alreadyInValidation = false; + } + + return (!empty($failureMap) ? $failureMap : true); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return mixed Value of field. + */ + public function getByName($name, $type = BasePeer::TYPE_PHPNAME) + { + $pos = CatalogPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->getByPosition($pos); + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch($pos) { + case 0: + return $this->getCatUid(); + break; + case 1: + return $this->getCatLabelId(); + break; + case 2: + return $this->getCatType(); + break; + case 3: + return $this->getCatFlag(); + break; + case 4: + return $this->getCatObservation(); + break; + case 5: + return $this->getCatCreateDate(); + break; + case 6: + return $this->getCatUpdateDate(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = BasePeer::TYPE_PHPNAME) + { + $keys = CatalogPeer::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getCatUid(), + $keys[1] => $this->getCatLabelId(), + $keys[2] => $this->getCatType(), + $keys[3] => $this->getCatFlag(), + $keys[4] => $this->getCatObservation(), + $keys[5] => $this->getCatCreateDate(), + $keys[6] => $this->getCatUpdateDate(), + ); + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name peer name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return void + */ + public function setByName($name, $value, $type = BasePeer::TYPE_PHPNAME) + { + $pos = CatalogPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch($pos) { + case 0: + $this->setCatUid($value); + break; + case 1: + $this->setCatLabelId($value); + break; + case 2: + $this->setCatType($value); + break; + case 3: + $this->setCatFlag($value); + break; + case 4: + $this->setCatObservation($value); + break; + case 5: + $this->setCatCreateDate($value); + break; + case 6: + $this->setCatUpdateDate($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, + * TYPE_NUM. The default key type is the column's phpname (e.g. 'authorId') + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = BasePeer::TYPE_PHPNAME) + { + $keys = CatalogPeer::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) { + $this->setCatUid($arr[$keys[0]]); + } + + if (array_key_exists($keys[1], $arr)) { + $this->setCatLabelId($arr[$keys[1]]); + } + + if (array_key_exists($keys[2], $arr)) { + $this->setCatType($arr[$keys[2]]); + } + + if (array_key_exists($keys[3], $arr)) { + $this->setCatFlag($arr[$keys[3]]); + } + + if (array_key_exists($keys[4], $arr)) { + $this->setCatObservation($arr[$keys[4]]); + } + + if (array_key_exists($keys[5], $arr)) { + $this->setCatCreateDate($arr[$keys[5]]); + } + + if (array_key_exists($keys[6], $arr)) { + $this->setCatUpdateDate($arr[$keys[6]]); + } + + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(CatalogPeer::DATABASE_NAME); + + if ($this->isColumnModified(CatalogPeer::CAT_UID)) { + $criteria->add(CatalogPeer::CAT_UID, $this->cat_uid); + } + + if ($this->isColumnModified(CatalogPeer::CAT_LABEL_ID)) { + $criteria->add(CatalogPeer::CAT_LABEL_ID, $this->cat_label_id); + } + + if ($this->isColumnModified(CatalogPeer::CAT_TYPE)) { + $criteria->add(CatalogPeer::CAT_TYPE, $this->cat_type); + } + + if ($this->isColumnModified(CatalogPeer::CAT_FLAG)) { + $criteria->add(CatalogPeer::CAT_FLAG, $this->cat_flag); + } + + if ($this->isColumnModified(CatalogPeer::CAT_OBSERVATION)) { + $criteria->add(CatalogPeer::CAT_OBSERVATION, $this->cat_observation); + } + + if ($this->isColumnModified(CatalogPeer::CAT_CREATE_DATE)) { + $criteria->add(CatalogPeer::CAT_CREATE_DATE, $this->cat_create_date); + } + + if ($this->isColumnModified(CatalogPeer::CAT_UPDATE_DATE)) { + $criteria->add(CatalogPeer::CAT_UPDATE_DATE, $this->cat_update_date); + } + + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(CatalogPeer::DATABASE_NAME); + + $criteria->add(CatalogPeer::CAT_UID, $this->cat_uid); + $criteria->add(CatalogPeer::CAT_TYPE, $this->cat_type); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + + $pks[0] = $this->getCatUid(); + + $pks[1] = $this->getCatType(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + + $this->setCatUid($keys[0]); + + $this->setCatType($keys[1]); + + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of Catalog (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false) + { + + $copyObj->setCatLabelId($this->cat_label_id); + + $copyObj->setCatFlag($this->cat_flag); + + $copyObj->setCatObservation($this->cat_observation); + + $copyObj->setCatCreateDate($this->cat_create_date); + + $copyObj->setCatUpdateDate($this->cat_update_date); + + + $copyObj->setNew(true); + + $copyObj->setCatUid('0'); // this is a pkey column, so set to default value + + $copyObj->setCatType(''); // this is a pkey column, so set to default value + + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return Catalog Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + return $copyObj; + } + + /** + * Returns a peer instance associated with this om. + * + * Since Peer classes are not to have any instance attributes, this method returns the + * same instance for all member of this class. The method could therefore + * be static, but this would prevent one from overriding the behavior. + * + * @return CatalogPeer + */ + public function getPeer() + { + if (self::$peer === null) { + self::$peer = new CatalogPeer(); + } + return self::$peer; + } +} + diff --git a/workflow/engine/classes/model/om/BaseCatalogPeer.php b/workflow/engine/classes/model/om/BaseCatalogPeer.php new file mode 100644 index 000000000..f4fee5e8d --- /dev/null +++ b/workflow/engine/classes/model/om/BaseCatalogPeer.php @@ -0,0 +1,587 @@ + array ('CatUid', 'CatLabelId', 'CatType', 'CatFlag', 'CatObservation', 'CatCreateDate', 'CatUpdateDate', ), + BasePeer::TYPE_COLNAME => array (CatalogPeer::CAT_UID, CatalogPeer::CAT_LABEL_ID, CatalogPeer::CAT_TYPE, CatalogPeer::CAT_FLAG, CatalogPeer::CAT_OBSERVATION, CatalogPeer::CAT_CREATE_DATE, CatalogPeer::CAT_UPDATE_DATE, ), + BasePeer::TYPE_FIELDNAME => array ('CAT_UID', 'CAT_LABEL_ID', 'CAT_TYPE', 'CAT_FLAG', 'CAT_OBSERVATION', 'CAT_CREATE_DATE', 'CAT_UPDATE_DATE', ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0 + */ + private static $fieldKeys = array ( + BasePeer::TYPE_PHPNAME => array ('CatUid' => 0, 'CatLabelId' => 1, 'CatType' => 2, 'CatFlag' => 3, 'CatObservation' => 4, 'CatCreateDate' => 5, 'CatUpdateDate' => 6, ), + BasePeer::TYPE_COLNAME => array (CatalogPeer::CAT_UID => 0, CatalogPeer::CAT_LABEL_ID => 1, CatalogPeer::CAT_TYPE => 2, CatalogPeer::CAT_FLAG => 3, CatalogPeer::CAT_OBSERVATION => 4, CatalogPeer::CAT_CREATE_DATE => 5, CatalogPeer::CAT_UPDATE_DATE => 6, ), + BasePeer::TYPE_FIELDNAME => array ('CAT_UID' => 0, 'CAT_LABEL_ID' => 1, 'CAT_TYPE' => 2, 'CAT_FLAG' => 3, 'CAT_OBSERVATION' => 4, 'CAT_CREATE_DATE' => 5, 'CAT_UPDATE_DATE' => 6, ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, ) + ); + + /** + * @return MapBuilder the map builder for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getMapBuilder() + { + include_once 'classes/model/map/CatalogMapBuilder.php'; + return BasePeer::getMapBuilder('classes.model.map.CatalogMapBuilder'); + } + /** + * Gets a map (hash) of PHP names to DB column names. + * + * @return array The PHP to DB name map for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @deprecated Use the getFieldNames() and translateFieldName() methods instead of this. + */ + public static function getPhpNameMap() + { + if (self::$phpNameMap === null) { + $map = CatalogPeer::getTableMap(); + $columns = $map->getColumns(); + $nameMap = array(); + foreach ($columns as $column) { + $nameMap[$column->getPhpName()] = $column->getColumnName(); + } + self::$phpNameMap = $nameMap; + } + return self::$phpNameMap; + } + /** + * Translates a fieldname to another type + * + * @param string $name field name + * @param string $fromType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @param string $toType One of the class type constants + * @return string translated name of the field. + */ + static public function translateFieldName($name, $fromType, $toType) + { + $toNames = self::getFieldNames($toType); + $key = isset(self::$fieldKeys[$fromType][$name]) ? self::$fieldKeys[$fromType][$name] : null; + if ($key === null) { + throw new PropelException("'$name' could not be found in the field names of type '$fromType'. These are: " . print_r(self::$fieldKeys[$fromType], true)); + } + return $toNames[$key]; + } + + /** + * Returns an array of of field names. + * + * @param string $type The type of fieldnames to return: + * One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return array A list of field names + */ + + static public function getFieldNames($type = BasePeer::TYPE_PHPNAME) + { + if (!array_key_exists($type, self::$fieldNames)) { + throw new PropelException('Method getFieldNames() expects the parameter $type to be one of the class constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM. ' . $type . ' was given.'); + } + return self::$fieldNames[$type]; + } + + /** + * Convenience method which changes table.column to alias.column. + * + * Using this method you can maintain SQL abstraction while using column aliases. + * + * $c->addAlias("alias1", TablePeer::TABLE_NAME); + * $c->addJoin(TablePeer::alias("alias1", TablePeer::PRIMARY_KEY_COLUMN), TablePeer::PRIMARY_KEY_COLUMN); + * + * @param string $alias The alias for the current table. + * @param string $column The column name for current table. (i.e. CatalogPeer::COLUMN_NAME). + * @return string + */ + public static function alias($alias, $column) + { + return str_replace(CatalogPeer::TABLE_NAME.'.', $alias.'.', $column); + } + + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param criteria object containing the columns to add. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria) + { + + $criteria->addSelectColumn(CatalogPeer::CAT_UID); + + $criteria->addSelectColumn(CatalogPeer::CAT_LABEL_ID); + + $criteria->addSelectColumn(CatalogPeer::CAT_TYPE); + + $criteria->addSelectColumn(CatalogPeer::CAT_FLAG); + + $criteria->addSelectColumn(CatalogPeer::CAT_OBSERVATION); + + $criteria->addSelectColumn(CatalogPeer::CAT_CREATE_DATE); + + $criteria->addSelectColumn(CatalogPeer::CAT_UPDATE_DATE); + + } + + const COUNT = 'COUNT(CATALOG.CAT_UID)'; + const COUNT_DISTINCT = 'COUNT(DISTINCT CATALOG.CAT_UID)'; + + /** + * Returns the number of rows matching criteria. + * + * @param Criteria $criteria + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCount(Criteria $criteria, $distinct = false, $con = null) + { + // we're going to modify criteria, so copy it first + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(CatalogPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(CatalogPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach ($criteria->getGroupByColumns() as $column) { + $criteria->addSelectColumn($column); + } + + $rs = CatalogPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + /** + * Method to select one object from the DB. + * + * @param Criteria $criteria object used to create the SELECT statement. + * @param Connection $con + * @return Catalog + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectOne(Criteria $criteria, $con = null) + { + $critcopy = clone $criteria; + $critcopy->setLimit(1); + $objects = CatalogPeer::doSelect($critcopy, $con); + if ($objects) { + return $objects[0]; + } + return null; + } + /** + * Method to do selects. + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con + * @return array Array of selected Objects + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelect(Criteria $criteria, $con = null) + { + return CatalogPeer::populateObjects(CatalogPeer::doSelectRS($criteria, $con)); + } + /** + * Prepares the Criteria object and uses the parent doSelect() + * method to get a ResultSet. + * + * Use this method directly if you want to just get the resultset + * (instead of an array of objects). + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con the connection to use + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return ResultSet The resultset object with numerically-indexed fields. + * @see BasePeer::doSelect() + */ + public static function doSelectRS(Criteria $criteria, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if (!$criteria->getSelectColumns()) { + $criteria = clone $criteria; + CatalogPeer::addSelectColumns($criteria); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + // BasePeer returns a Creole ResultSet, set to return + // rows indexed numerically. + return BasePeer::doSelect($criteria, $con); + } + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(ResultSet $rs) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = CatalogPeer::getOMClass(); + $cls = Propel::import($cls); + // populate the object(s) + while ($rs->next()) { + + $obj = new $cls(); + $obj->hydrate($rs); + $results[] = $obj; + + } + return $results; + } + /** + * Returns the TableMap related to this peer. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getDatabaseMap(self::DATABASE_NAME)->getTable(self::TABLE_NAME); + } + + /** + * The class that the Peer will make instances of. + * + * This uses a dot-path notation which is tranalted into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @return string path.to.ClassName + */ + public static function getOMClass() + { + return CatalogPeer::CLASS_DEFAULT; + } + + /** + * Method perform an INSERT on the database, given a Catalog or Criteria object. + * + * @param mixed $values Criteria or Catalog object containing data that is used to create the INSERT statement. + * @param Connection $con the connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } else { + $criteria = $values->buildCriteria(); // build Criteria from Catalog object + } + + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->begin(); + $pk = BasePeer::doInsert($criteria, $con); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + + return $pk; + } + + /** + * Method perform an UPDATE on the database, given a Catalog or Criteria object. + * + * @param mixed $values Criteria or Catalog object containing data create the UPDATE statement. + * @param Connection $con The connection to use (specify Connection exert more control over transactions). + * @return int The number of affected rows (if supported by underlying database driver). + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doUpdate($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $selectCriteria = new Criteria(self::DATABASE_NAME); + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + + $comparison = $criteria->getComparison(CatalogPeer::CAT_UID); + $selectCriteria->add(CatalogPeer::CAT_UID, $criteria->remove(CatalogPeer::CAT_UID), $comparison); + + $comparison = $criteria->getComparison(CatalogPeer::CAT_TYPE); + $selectCriteria->add(CatalogPeer::CAT_TYPE, $criteria->remove(CatalogPeer::CAT_TYPE), $comparison); + + } else { + $criteria = $values->buildCriteria(); // gets full criteria + $selectCriteria = $values->buildPkeyCriteria(); // gets criteria w/ primary key(s) + } + + // set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + return BasePeer::doUpdate($selectCriteria, $criteria, $con); + } + + /** + * Method to DELETE all rows from the CATALOG table. + * + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll($con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + $affectedRows += BasePeer::doDeleteAll(CatalogPeer::TABLE_NAME, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Method perform a DELETE on the database, given a Catalog or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or Catalog object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param Connection $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + * This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(CatalogPeer::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } elseif ($values instanceof Catalog) { + + $criteria = $values->buildPkeyCriteria(); + } else { + // it must be the primary key + $criteria = new Criteria(self::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey + // values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + $vals = array(); + foreach ($values as $value) { + + $vals[0][] = $value[0]; + $vals[1][] = $value[1]; + } + + $criteria->add(CatalogPeer::CAT_UID, $vals[0], Criteria::IN); + $criteria->add(CatalogPeer::CAT_TYPE, $vals[1], Criteria::IN); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + + $affectedRows += BasePeer::doDelete($criteria, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Validates all modified columns of given Catalog object. + * If parameter $columns is either a single column name or an array of column names + * than only those columns are validated. + * + * NOTICE: This does not apply to primary or foreign keys for now. + * + * @param Catalog $obj The object to validate. + * @param mixed $cols Column name or array of column names. + * + * @return mixed TRUE if all columns are valid or the error message of the first invalid column. + */ + public static function doValidate(Catalog $obj, $cols = null) + { + $columns = array(); + + if ($cols) { + $dbMap = Propel::getDatabaseMap(CatalogPeer::DATABASE_NAME); + $tableMap = $dbMap->getTable(CatalogPeer::TABLE_NAME); + + if (! is_array($cols)) { + $cols = array($cols); + } + + foreach ($cols as $colName) { + if ($tableMap->containsColumn($colName)) { + $get = 'get' . $tableMap->getColumn($colName)->getPhpName(); + $columns[$colName] = $obj->$get(); + } + } + } else { + + } + + return BasePeer::doValidate(CatalogPeer::DATABASE_NAME, CatalogPeer::TABLE_NAME, $columns); + } + + /** + * Retrieve object using using composite pkey values. + * @param string $cat_uid + * @param string $cat_type + * @param Connection $con + * @return Catalog + */ + public static function retrieveByPK($cat_uid, $cat_type, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $criteria = new Criteria(); + $criteria->add(CatalogPeer::CAT_UID, $cat_uid); + $criteria->add(CatalogPeer::CAT_TYPE, $cat_type); + $v = CatalogPeer::doSelect($criteria, $con); + + return !empty($v) ? $v[0] : null; + } +} + + +// static code to register the map builder for this Peer with the main Propel class +if (Propel::isInit()) { + // the MapBuilder classes register themselves with Propel during initialization + // so we need to load them here. + try { + BaseCatalogPeer::getMapBuilder(); + } catch (Exception $e) { + Propel::log('Could not initialize Peer: ' . $e->getMessage(), Propel::LOG_ERR); + } +} else { + // even if Propel is not yet initialized, the map builder class can be registered + // now and then it will be loaded when Propel initializes. + require_once 'classes/model/map/CatalogMapBuilder.php'; + Propel::registerMapBuilder('classes.model.map.CatalogMapBuilder'); +} + diff --git a/workflow/engine/classes/model/om/BaseDashboard.php b/workflow/engine/classes/model/om/BaseDashboard.php new file mode 100644 index 000000000..250744658 --- /dev/null +++ b/workflow/engine/classes/model/om/BaseDashboard.php @@ -0,0 +1,1142 @@ +das_uid; + } + + /** + * Get the [das_title] column value. + * + * @return string + */ + public function getDasTitle() + { + + return $this->das_title; + } + + /** + * Get the [das_description] column value. + * + * @return string + */ + public function getDasDescription() + { + + return $this->das_description; + } + + /** + * Get the [optionally formatted] [das_create_date] column value. + * + * @param string $format The date/time format string (either date()-style or strftime()-style). + * If format is NULL, then the integer unix timestamp will be returned. + * @return mixed Formatted date/time value as string or integer unix timestamp (if format is NULL). + * @throws PropelException - if unable to convert the date/time to timestamp. + */ + public function getDasCreateDate($format = 'Y-m-d H:i:s') + { + + if ($this->das_create_date === null || $this->das_create_date === '') { + return null; + } elseif (!is_int($this->das_create_date)) { + // a non-timestamp value was set externally, so we convert it + $ts = strtotime($this->das_create_date); + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse value of [das_create_date] as date/time value: " . + var_export($this->das_create_date, true)); + } + } else { + $ts = $this->das_create_date; + } + if ($format === null) { + return $ts; + } elseif (strpos($format, '%') !== false) { + return strftime($format, $ts); + } else { + return date($format, $ts); + } + } + + /** + * Get the [optionally formatted] [das_update_date] column value. + * + * @param string $format The date/time format string (either date()-style or strftime()-style). + * If format is NULL, then the integer unix timestamp will be returned. + * @return mixed Formatted date/time value as string or integer unix timestamp (if format is NULL). + * @throws PropelException - if unable to convert the date/time to timestamp. + */ + public function getDasUpdateDate($format = 'Y-m-d H:i:s') + { + + if ($this->das_update_date === null || $this->das_update_date === '') { + return null; + } elseif (!is_int($this->das_update_date)) { + // a non-timestamp value was set externally, so we convert it + $ts = strtotime($this->das_update_date); + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse value of [das_update_date] as date/time value: " . + var_export($this->das_update_date, true)); + } + } else { + $ts = $this->das_update_date; + } + if ($format === null) { + return $ts; + } elseif (strpos($format, '%') !== false) { + return strftime($format, $ts); + } else { + return date($format, $ts); + } + } + + /** + * Get the [das_status] column value. + * + * @return int + */ + public function getDasStatus() + { + + return $this->das_status; + } + + /** + * Set the value of [das_uid] column. + * + * @param string $v new value + * @return void + */ + public function setDasUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_uid !== $v || $v === '') { + $this->das_uid = $v; + $this->modifiedColumns[] = DashboardPeer::DAS_UID; + } + + } // setDasUid() + + /** + * Set the value of [das_title] column. + * + * @param string $v new value + * @return void + */ + public function setDasTitle($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_title !== $v || $v === '') { + $this->das_title = $v; + $this->modifiedColumns[] = DashboardPeer::DAS_TITLE; + } + + } // setDasTitle() + + /** + * Set the value of [das_description] column. + * + * @param string $v new value + * @return void + */ + public function setDasDescription($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_description !== $v) { + $this->das_description = $v; + $this->modifiedColumns[] = DashboardPeer::DAS_DESCRIPTION; + } + + } // setDasDescription() + + /** + * Set the value of [das_create_date] column. + * + * @param int $v new value + * @return void + */ + public function setDasCreateDate($v) + { + + if ($v !== null && !is_int($v)) { + $ts = strtotime($v); + //Date/time accepts null values + if ($v == '') { + $ts = null; + } + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse date/time value for [das_create_date] from input: " . + var_export($v, true)); + } + } else { + $ts = $v; + } + if ($this->das_create_date !== $ts) { + $this->das_create_date = $ts; + $this->modifiedColumns[] = DashboardPeer::DAS_CREATE_DATE; + } + + } // setDasCreateDate() + + /** + * Set the value of [das_update_date] column. + * + * @param int $v new value + * @return void + */ + public function setDasUpdateDate($v) + { + + if ($v !== null && !is_int($v)) { + $ts = strtotime($v); + //Date/time accepts null values + if ($v == '') { + $ts = null; + } + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse date/time value for [das_update_date] from input: " . + var_export($v, true)); + } + } else { + $ts = $v; + } + if ($this->das_update_date !== $ts) { + $this->das_update_date = $ts; + $this->modifiedColumns[] = DashboardPeer::DAS_UPDATE_DATE; + } + + } // setDasUpdateDate() + + /** + * Set the value of [das_status] column. + * + * @param int $v new value + * @return void + */ + public function setDasStatus($v) + { + + // Since the native PHP type for this column is integer, + // we will cast the input value to an int (if it is not). + if ($v !== null && !is_int($v) && is_numeric($v)) { + $v = (int) $v; + } + + if ($this->das_status !== $v || $v === 1) { + $this->das_status = $v; + $this->modifiedColumns[] = DashboardPeer::DAS_STATUS; + } + + } // setDasStatus() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (1-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param ResultSet $rs The ResultSet class with cursor advanced to desired record pos. + * @param int $startcol 1-based offset column which indicates which restultset column to start with. + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate(ResultSet $rs, $startcol = 1) + { + try { + + $this->das_uid = $rs->getString($startcol + 0); + + $this->das_title = $rs->getString($startcol + 1); + + $this->das_description = $rs->getString($startcol + 2); + + $this->das_create_date = $rs->getTimestamp($startcol + 3, null); + + $this->das_update_date = $rs->getTimestamp($startcol + 4, null); + + $this->das_status = $rs->getInt($startcol + 5); + + $this->resetModified(); + + $this->setNew(false); + + // FIXME - using NUM_COLUMNS may be clearer. + return $startcol + 6; // 6 = DashboardPeer::NUM_COLUMNS - DashboardPeer::NUM_LAZY_LOAD_COLUMNS). + + } catch (Exception $e) { + throw new PropelException("Error populating Dashboard object", $e); + } + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param Connection $con + * @return void + * @throws PropelException + * @see BaseObject::setDeleted() + * @see BaseObject::isDeleted() + */ + public function delete($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(DashboardPeer::DATABASE_NAME); + } + + try { + $con->begin(); + DashboardPeer::doDelete($this, $con); + $this->setDeleted(true); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. If the object is new, + * it inserts it; otherwise an update is performed. This method + * wraps the doSave() worker method in a transaction. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update + * @throws PropelException + * @see doSave() + */ + public function save($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(DashboardPeer::DATABASE_NAME); + } + + try { + $con->begin(); + $affectedRows = $this->doSave($con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update and any referring + * @throws PropelException + * @see save() + */ + protected function doSave($con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + + // If this object has been modified, then save it to the database. + if ($this->isModified()) { + if ($this->isNew()) { + $pk = DashboardPeer::doInsert($this, $con); + $affectedRows += 1; // we are assuming that there is only 1 row per doInsert() which + // should always be true here (even though technically + // BasePeer::doInsert() can insert multiple rows). + + $this->setNew(false); + } else { + $affectedRows += DashboardPeer::doUpdate($this, $con); + } + $this->resetModified(); // [HL] After being saved an object is no longer 'modified' + } + + if ($this->collDashboardIndicators !== null) { + foreach($this->collDashboardIndicators as $referrerFK) { + if (!$referrerFK->isDeleted()) { + $affectedRows += $referrerFK->save($con); + } + } + } + + if ($this->collDashboardDasInds !== null) { + foreach($this->collDashboardDasInds as $referrerFK) { + if (!$referrerFK->isDeleted()) { + $affectedRows += $referrerFK->save($con); + } + } + } + + $this->alreadyInSave = false; + } + return $affectedRows; + } // doSave() + + /** + * Array of ValidationFailed objects. + * @var array ValidationFailed[] + */ + protected $validationFailures = array(); + + /** + * Gets any ValidationFailed objects that resulted from last call to validate(). + * + * + * @return array ValidationFailed[] + * @see validate() + */ + public function getValidationFailures() + { + return $this->validationFailures; + } + + /** + * Validates the objects modified field values and all objects related to this table. + * + * If $columns is either a column name or an array of column names + * only those columns are validated. + * + * @param mixed $columns Column name or an array of column names. + * @return boolean Whether all columns pass validation. + * @see doValidate() + * @see getValidationFailures() + */ + public function validate($columns = null) + { + $res = $this->doValidate($columns); + if ($res === true) { + $this->validationFailures = array(); + return true; + } else { + $this->validationFailures = $res; + return false; + } + } + + /** + * This function performs the validation work for complex object models. + * + * In addition to checking the current object, all related objects will + * also be validated. If all pass then true is returned; otherwise + * an aggreagated array of ValidationFailed objects will be returned. + * + * @param array $columns Array of column names to validate. + * @return mixed true if all validations pass; + array of ValidationFailed objects otherwise. + */ + protected function doValidate($columns = null) + { + if (!$this->alreadyInValidation) { + $this->alreadyInValidation = true; + $retval = null; + + $failureMap = array(); + + + if (($retval = DashboardPeer::doValidate($this, $columns)) !== true) { + $failureMap = array_merge($failureMap, $retval); + } + + + if ($this->collDashboardIndicators !== null) { + foreach($this->collDashboardIndicators as $referrerFK) { + if (!$referrerFK->validate($columns)) { + $failureMap = array_merge($failureMap, $referrerFK->getValidationFailures()); + } + } + } + + if ($this->collDashboardDasInds !== null) { + foreach($this->collDashboardDasInds as $referrerFK) { + if (!$referrerFK->validate($columns)) { + $failureMap = array_merge($failureMap, $referrerFK->getValidationFailures()); + } + } + } + + + $this->alreadyInValidation = false; + } + + return (!empty($failureMap) ? $failureMap : true); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return mixed Value of field. + */ + public function getByName($name, $type = BasePeer::TYPE_PHPNAME) + { + $pos = DashboardPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->getByPosition($pos); + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch($pos) { + case 0: + return $this->getDasUid(); + break; + case 1: + return $this->getDasTitle(); + break; + case 2: + return $this->getDasDescription(); + break; + case 3: + return $this->getDasCreateDate(); + break; + case 4: + return $this->getDasUpdateDate(); + break; + case 5: + return $this->getDasStatus(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = BasePeer::TYPE_PHPNAME) + { + $keys = DashboardPeer::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getDasUid(), + $keys[1] => $this->getDasTitle(), + $keys[2] => $this->getDasDescription(), + $keys[3] => $this->getDasCreateDate(), + $keys[4] => $this->getDasUpdateDate(), + $keys[5] => $this->getDasStatus(), + ); + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name peer name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return void + */ + public function setByName($name, $value, $type = BasePeer::TYPE_PHPNAME) + { + $pos = DashboardPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch($pos) { + case 0: + $this->setDasUid($value); + break; + case 1: + $this->setDasTitle($value); + break; + case 2: + $this->setDasDescription($value); + break; + case 3: + $this->setDasCreateDate($value); + break; + case 4: + $this->setDasUpdateDate($value); + break; + case 5: + $this->setDasStatus($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, + * TYPE_NUM. The default key type is the column's phpname (e.g. 'authorId') + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = BasePeer::TYPE_PHPNAME) + { + $keys = DashboardPeer::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) { + $this->setDasUid($arr[$keys[0]]); + } + + if (array_key_exists($keys[1], $arr)) { + $this->setDasTitle($arr[$keys[1]]); + } + + if (array_key_exists($keys[2], $arr)) { + $this->setDasDescription($arr[$keys[2]]); + } + + if (array_key_exists($keys[3], $arr)) { + $this->setDasCreateDate($arr[$keys[3]]); + } + + if (array_key_exists($keys[4], $arr)) { + $this->setDasUpdateDate($arr[$keys[4]]); + } + + if (array_key_exists($keys[5], $arr)) { + $this->setDasStatus($arr[$keys[5]]); + } + + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(DashboardPeer::DATABASE_NAME); + + if ($this->isColumnModified(DashboardPeer::DAS_UID)) { + $criteria->add(DashboardPeer::DAS_UID, $this->das_uid); + } + + if ($this->isColumnModified(DashboardPeer::DAS_TITLE)) { + $criteria->add(DashboardPeer::DAS_TITLE, $this->das_title); + } + + if ($this->isColumnModified(DashboardPeer::DAS_DESCRIPTION)) { + $criteria->add(DashboardPeer::DAS_DESCRIPTION, $this->das_description); + } + + if ($this->isColumnModified(DashboardPeer::DAS_CREATE_DATE)) { + $criteria->add(DashboardPeer::DAS_CREATE_DATE, $this->das_create_date); + } + + if ($this->isColumnModified(DashboardPeer::DAS_UPDATE_DATE)) { + $criteria->add(DashboardPeer::DAS_UPDATE_DATE, $this->das_update_date); + } + + if ($this->isColumnModified(DashboardPeer::DAS_STATUS)) { + $criteria->add(DashboardPeer::DAS_STATUS, $this->das_status); + } + + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(DashboardPeer::DATABASE_NAME); + + $criteria->add(DashboardPeer::DAS_UID, $this->das_uid); + + return $criteria; + } + + /** + * Returns the primary key for this object (row). + * @return string + */ + public function getPrimaryKey() + { + return $this->getDasUid(); + } + + /** + * Generic method to set the primary key (das_uid column). + * + * @param string $key Primary key. + * @return void + */ + public function setPrimaryKey($key) + { + $this->setDasUid($key); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of Dashboard (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false) + { + + $copyObj->setDasTitle($this->das_title); + + $copyObj->setDasDescription($this->das_description); + + $copyObj->setDasCreateDate($this->das_create_date); + + $copyObj->setDasUpdateDate($this->das_update_date); + + $copyObj->setDasStatus($this->das_status); + + + if ($deepCopy) { + // important: temporarily setNew(false) because this affects the behavior of + // the getter/setter methods for fkey referrer objects. + $copyObj->setNew(false); + + foreach($this->getDashboardIndicators() as $relObj) { + $copyObj->addDashboardIndicator($relObj->copy($deepCopy)); + } + + foreach($this->getDashboardDasInds() as $relObj) { + $copyObj->addDashboardDasInd($relObj->copy($deepCopy)); + } + + } // if ($deepCopy) + + + $copyObj->setNew(true); + + $copyObj->setDasUid(''); // this is a pkey column, so set to default value + + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return Dashboard Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + return $copyObj; + } + + /** + * Returns a peer instance associated with this om. + * + * Since Peer classes are not to have any instance attributes, this method returns the + * same instance for all member of this class. The method could therefore + * be static, but this would prevent one from overriding the behavior. + * + * @return DashboardPeer + */ + public function getPeer() + { + if (self::$peer === null) { + self::$peer = new DashboardPeer(); + } + return self::$peer; + } + + /** + * Temporary storage of collDashboardIndicators to save a possible db hit in + * the event objects are add to the collection, but the + * complete collection is never requested. + * @return void + */ + public function initDashboardIndicators() + { + if ($this->collDashboardIndicators === null) { + $this->collDashboardIndicators = array(); + } + } + + /** + * If this collection has already been initialized with + * an identical criteria, it returns the collection. + * Otherwise if this Dashboard has previously + * been saved, it will retrieve related DashboardIndicators from storage. + * If this Dashboard is new, it will return + * an empty collection or the current collection, the criteria + * is ignored on a new object. + * + * @param Connection $con + * @param Criteria $criteria + * @throws PropelException + */ + public function getDashboardIndicators($criteria = null, $con = null) + { + // include the Peer class + include_once 'classes/model/om/BaseDashboardIndicatorPeer.php'; + if ($criteria === null) { + $criteria = new Criteria(); + } + elseif ($criteria instanceof Criteria) + { + $criteria = clone $criteria; + } + + if ($this->collDashboardIndicators === null) { + if ($this->isNew()) { + $this->collDashboardIndicators = array(); + } else { + + $criteria->add(DashboardIndicatorPeer::DAS_UID, $this->getDasUid()); + + DashboardIndicatorPeer::addSelectColumns($criteria); + $this->collDashboardIndicators = DashboardIndicatorPeer::doSelect($criteria, $con); + } + } else { + // criteria has no effect for a new object + if (!$this->isNew()) { + // the following code is to determine if a new query is + // called for. If the criteria is the same as the last + // one, just return the collection. + + + $criteria->add(DashboardIndicatorPeer::DAS_UID, $this->getDasUid()); + + DashboardIndicatorPeer::addSelectColumns($criteria); + if (!isset($this->lastDashboardIndicatorCriteria) || !$this->lastDashboardIndicatorCriteria->equals($criteria)) { + $this->collDashboardIndicators = DashboardIndicatorPeer::doSelect($criteria, $con); + } + } + } + $this->lastDashboardIndicatorCriteria = $criteria; + return $this->collDashboardIndicators; + } + + /** + * Returns the number of related DashboardIndicators. + * + * @param Criteria $criteria + * @param boolean $distinct + * @param Connection $con + * @throws PropelException + */ + public function countDashboardIndicators($criteria = null, $distinct = false, $con = null) + { + // include the Peer class + include_once 'classes/model/om/BaseDashboardIndicatorPeer.php'; + if ($criteria === null) { + $criteria = new Criteria(); + } + elseif ($criteria instanceof Criteria) + { + $criteria = clone $criteria; + } + + $criteria->add(DashboardIndicatorPeer::DAS_UID, $this->getDasUid()); + + return DashboardIndicatorPeer::doCount($criteria, $distinct, $con); + } + + /** + * Method called to associate a DashboardIndicator object to this object + * through the DashboardIndicator foreign key attribute + * + * @param DashboardIndicator $l DashboardIndicator + * @return void + * @throws PropelException + */ + public function addDashboardIndicator(DashboardIndicator $l) + { + $this->collDashboardIndicators[] = $l; + $l->setDashboard($this); + } + + /** + * Temporary storage of collDashboardDasInds to save a possible db hit in + * the event objects are add to the collection, but the + * complete collection is never requested. + * @return void + */ + public function initDashboardDasInds() + { + if ($this->collDashboardDasInds === null) { + $this->collDashboardDasInds = array(); + } + } + + /** + * If this collection has already been initialized with + * an identical criteria, it returns the collection. + * Otherwise if this Dashboard has previously + * been saved, it will retrieve related DashboardDasInds from storage. + * If this Dashboard is new, it will return + * an empty collection or the current collection, the criteria + * is ignored on a new object. + * + * @param Connection $con + * @param Criteria $criteria + * @throws PropelException + */ + public function getDashboardDasInds($criteria = null, $con = null) + { + // include the Peer class + include_once 'classes/model/om/BaseDashboardDasIndPeer.php'; + if ($criteria === null) { + $criteria = new Criteria(); + } + elseif ($criteria instanceof Criteria) + { + $criteria = clone $criteria; + } + + if ($this->collDashboardDasInds === null) { + if ($this->isNew()) { + $this->collDashboardDasInds = array(); + } else { + + $criteria->add(DashboardDasIndPeer::DAS_UID, $this->getDasUid()); + + DashboardDasIndPeer::addSelectColumns($criteria); + $this->collDashboardDasInds = DashboardDasIndPeer::doSelect($criteria, $con); + } + } else { + // criteria has no effect for a new object + if (!$this->isNew()) { + // the following code is to determine if a new query is + // called for. If the criteria is the same as the last + // one, just return the collection. + + + $criteria->add(DashboardDasIndPeer::DAS_UID, $this->getDasUid()); + + DashboardDasIndPeer::addSelectColumns($criteria); + if (!isset($this->lastDashboardDasIndCriteria) || !$this->lastDashboardDasIndCriteria->equals($criteria)) { + $this->collDashboardDasInds = DashboardDasIndPeer::doSelect($criteria, $con); + } + } + } + $this->lastDashboardDasIndCriteria = $criteria; + return $this->collDashboardDasInds; + } + + /** + * Returns the number of related DashboardDasInds. + * + * @param Criteria $criteria + * @param boolean $distinct + * @param Connection $con + * @throws PropelException + */ + public function countDashboardDasInds($criteria = null, $distinct = false, $con = null) + { + // include the Peer class + include_once 'classes/model/om/BaseDashboardDasIndPeer.php'; + if ($criteria === null) { + $criteria = new Criteria(); + } + elseif ($criteria instanceof Criteria) + { + $criteria = clone $criteria; + } + + $criteria->add(DashboardDasIndPeer::DAS_UID, $this->getDasUid()); + + return DashboardDasIndPeer::doCount($criteria, $distinct, $con); + } + + /** + * Method called to associate a DashboardDasInd object to this object + * through the DashboardDasInd foreign key attribute + * + * @param DashboardDasInd $l DashboardDasInd + * @return void + * @throws PropelException + */ + public function addDashboardDasInd(DashboardDasInd $l) + { + $this->collDashboardDasInds[] = $l; + $l->setDashboard($this); + } +} + diff --git a/workflow/engine/classes/model/om/BaseDashboardDasInd.php b/workflow/engine/classes/model/om/BaseDashboardDasInd.php new file mode 100644 index 000000000..1b787d1c9 --- /dev/null +++ b/workflow/engine/classes/model/om/BaseDashboardDasInd.php @@ -0,0 +1,723 @@ +das_uid; + } + + /** + * Get the [owner_uid] column value. + * + * @return string + */ + public function getOwnerUid() + { + + return $this->owner_uid; + } + + /** + * Get the [owner_type] column value. + * + * @return string + */ + public function getOwnerType() + { + + return $this->owner_type; + } + + /** + * Set the value of [das_uid] column. + * + * @param string $v new value + * @return void + */ + public function setDasUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_uid !== $v || $v === '') { + $this->das_uid = $v; + $this->modifiedColumns[] = DashboardDasIndPeer::DAS_UID; + } + + if ($this->aDashboard !== null && $this->aDashboard->getDasUid() !== $v) { + $this->aDashboard = null; + } + + } // setDasUid() + + /** + * Set the value of [owner_uid] column. + * + * @param string $v new value + * @return void + */ + public function setOwnerUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->owner_uid !== $v || $v === '') { + $this->owner_uid = $v; + $this->modifiedColumns[] = DashboardDasIndPeer::OWNER_UID; + } + + } // setOwnerUid() + + /** + * Set the value of [owner_type] column. + * + * @param string $v new value + * @return void + */ + public function setOwnerType($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->owner_type !== $v || $v === '') { + $this->owner_type = $v; + $this->modifiedColumns[] = DashboardDasIndPeer::OWNER_TYPE; + } + + } // setOwnerType() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (1-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param ResultSet $rs The ResultSet class with cursor advanced to desired record pos. + * @param int $startcol 1-based offset column which indicates which restultset column to start with. + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate(ResultSet $rs, $startcol = 1) + { + try { + + $this->das_uid = $rs->getString($startcol + 0); + + $this->owner_uid = $rs->getString($startcol + 1); + + $this->owner_type = $rs->getString($startcol + 2); + + $this->resetModified(); + + $this->setNew(false); + + // FIXME - using NUM_COLUMNS may be clearer. + return $startcol + 3; // 3 = DashboardDasIndPeer::NUM_COLUMNS - DashboardDasIndPeer::NUM_LAZY_LOAD_COLUMNS). + + } catch (Exception $e) { + throw new PropelException("Error populating DashboardDasInd object", $e); + } + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param Connection $con + * @return void + * @throws PropelException + * @see BaseObject::setDeleted() + * @see BaseObject::isDeleted() + */ + public function delete($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(DashboardDasIndPeer::DATABASE_NAME); + } + + try { + $con->begin(); + DashboardDasIndPeer::doDelete($this, $con); + $this->setDeleted(true); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. If the object is new, + * it inserts it; otherwise an update is performed. This method + * wraps the doSave() worker method in a transaction. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update + * @throws PropelException + * @see doSave() + */ + public function save($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(DashboardDasIndPeer::DATABASE_NAME); + } + + try { + $con->begin(); + $affectedRows = $this->doSave($con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update and any referring + * @throws PropelException + * @see save() + */ + protected function doSave($con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + + // We call the save method on the following object(s) if they + // were passed to this object by their coresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aDashboard !== null) { + if ($this->aDashboard->isModified()) { + $affectedRows += $this->aDashboard->save($con); + } + $this->setDashboard($this->aDashboard); + } + + + // If this object has been modified, then save it to the database. + if ($this->isModified()) { + if ($this->isNew()) { + $pk = DashboardDasIndPeer::doInsert($this, $con); + $affectedRows += 1; // we are assuming that there is only 1 row per doInsert() which + // should always be true here (even though technically + // BasePeer::doInsert() can insert multiple rows). + + $this->setNew(false); + } else { + $affectedRows += DashboardDasIndPeer::doUpdate($this, $con); + } + $this->resetModified(); // [HL] After being saved an object is no longer 'modified' + } + + $this->alreadyInSave = false; + } + return $affectedRows; + } // doSave() + + /** + * Array of ValidationFailed objects. + * @var array ValidationFailed[] + */ + protected $validationFailures = array(); + + /** + * Gets any ValidationFailed objects that resulted from last call to validate(). + * + * + * @return array ValidationFailed[] + * @see validate() + */ + public function getValidationFailures() + { + return $this->validationFailures; + } + + /** + * Validates the objects modified field values and all objects related to this table. + * + * If $columns is either a column name or an array of column names + * only those columns are validated. + * + * @param mixed $columns Column name or an array of column names. + * @return boolean Whether all columns pass validation. + * @see doValidate() + * @see getValidationFailures() + */ + public function validate($columns = null) + { + $res = $this->doValidate($columns); + if ($res === true) { + $this->validationFailures = array(); + return true; + } else { + $this->validationFailures = $res; + return false; + } + } + + /** + * This function performs the validation work for complex object models. + * + * In addition to checking the current object, all related objects will + * also be validated. If all pass then true is returned; otherwise + * an aggreagated array of ValidationFailed objects will be returned. + * + * @param array $columns Array of column names to validate. + * @return mixed true if all validations pass; + array of ValidationFailed objects otherwise. + */ + protected function doValidate($columns = null) + { + if (!$this->alreadyInValidation) { + $this->alreadyInValidation = true; + $retval = null; + + $failureMap = array(); + + + // We call the validate method on the following object(s) if they + // were passed to this object by their coresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aDashboard !== null) { + if (!$this->aDashboard->validate($columns)) { + $failureMap = array_merge($failureMap, $this->aDashboard->getValidationFailures()); + } + } + + + if (($retval = DashboardDasIndPeer::doValidate($this, $columns)) !== true) { + $failureMap = array_merge($failureMap, $retval); + } + + + + $this->alreadyInValidation = false; + } + + return (!empty($failureMap) ? $failureMap : true); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return mixed Value of field. + */ + public function getByName($name, $type = BasePeer::TYPE_PHPNAME) + { + $pos = DashboardDasIndPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->getByPosition($pos); + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch($pos) { + case 0: + return $this->getDasUid(); + break; + case 1: + return $this->getOwnerUid(); + break; + case 2: + return $this->getOwnerType(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = BasePeer::TYPE_PHPNAME) + { + $keys = DashboardDasIndPeer::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getDasUid(), + $keys[1] => $this->getOwnerUid(), + $keys[2] => $this->getOwnerType(), + ); + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name peer name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return void + */ + public function setByName($name, $value, $type = BasePeer::TYPE_PHPNAME) + { + $pos = DashboardDasIndPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch($pos) { + case 0: + $this->setDasUid($value); + break; + case 1: + $this->setOwnerUid($value); + break; + case 2: + $this->setOwnerType($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, + * TYPE_NUM. The default key type is the column's phpname (e.g. 'authorId') + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = BasePeer::TYPE_PHPNAME) + { + $keys = DashboardDasIndPeer::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) { + $this->setDasUid($arr[$keys[0]]); + } + + if (array_key_exists($keys[1], $arr)) { + $this->setOwnerUid($arr[$keys[1]]); + } + + if (array_key_exists($keys[2], $arr)) { + $this->setOwnerType($arr[$keys[2]]); + } + + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(DashboardDasIndPeer::DATABASE_NAME); + + if ($this->isColumnModified(DashboardDasIndPeer::DAS_UID)) { + $criteria->add(DashboardDasIndPeer::DAS_UID, $this->das_uid); + } + + if ($this->isColumnModified(DashboardDasIndPeer::OWNER_UID)) { + $criteria->add(DashboardDasIndPeer::OWNER_UID, $this->owner_uid); + } + + if ($this->isColumnModified(DashboardDasIndPeer::OWNER_TYPE)) { + $criteria->add(DashboardDasIndPeer::OWNER_TYPE, $this->owner_type); + } + + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(DashboardDasIndPeer::DATABASE_NAME); + + $criteria->add(DashboardDasIndPeer::DAS_UID, $this->das_uid); + $criteria->add(DashboardDasIndPeer::OWNER_UID, $this->owner_uid); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + + $pks[0] = $this->getDasUid(); + + $pks[1] = $this->getOwnerUid(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + + $this->setDasUid($keys[0]); + + $this->setOwnerUid($keys[1]); + + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of DashboardDasInd (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false) + { + + $copyObj->setOwnerType($this->owner_type); + + + $copyObj->setNew(true); + + $copyObj->setDasUid(''); // this is a pkey column, so set to default value + + $copyObj->setOwnerUid(''); // this is a pkey column, so set to default value + + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return DashboardDasInd Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + return $copyObj; + } + + /** + * Returns a peer instance associated with this om. + * + * Since Peer classes are not to have any instance attributes, this method returns the + * same instance for all member of this class. The method could therefore + * be static, but this would prevent one from overriding the behavior. + * + * @return DashboardDasIndPeer + */ + public function getPeer() + { + if (self::$peer === null) { + self::$peer = new DashboardDasIndPeer(); + } + return self::$peer; + } + + /** + * Declares an association between this object and a Dashboard object. + * + * @param Dashboard $v + * @return void + * @throws PropelException + */ + public function setDashboard($v) + { + + + if ($v === null) { + $this->setDasUid(''); + } else { + $this->setDasUid($v->getDasUid()); + } + + + $this->aDashboard = $v; + } + + + /** + * Get the associated Dashboard object + * + * @param Connection Optional Connection object. + * @return Dashboard The associated Dashboard object. + * @throws PropelException + */ + public function getDashboard($con = null) + { + // include the related Peer class + include_once 'classes/model/om/BaseDashboardPeer.php'; + + if ($this->aDashboard === null && (($this->das_uid !== "" && $this->das_uid !== null))) { + + $this->aDashboard = DashboardPeer::retrieveByPK($this->das_uid, $con); + + /* The following can be used instead of the line above to + guarantee the related object contains a reference + to this object, but this level of coupling + may be undesirable in many circumstances. + As it can lead to a db query with many results that may + never be used. + $obj = DashboardPeer::retrieveByPK($this->das_uid, $con); + $obj->addDashboards($this); + */ + } + return $this->aDashboard; + } +} + diff --git a/workflow/engine/classes/model/om/BaseDashboardDasIndPeer.php b/workflow/engine/classes/model/om/BaseDashboardDasIndPeer.php new file mode 100644 index 000000000..eb943b02f --- /dev/null +++ b/workflow/engine/classes/model/om/BaseDashboardDasIndPeer.php @@ -0,0 +1,770 @@ + array ('DasUid', 'OwnerUid', 'OwnerType', ), + BasePeer::TYPE_COLNAME => array (DashboardDasIndPeer::DAS_UID, DashboardDasIndPeer::OWNER_UID, DashboardDasIndPeer::OWNER_TYPE, ), + BasePeer::TYPE_FIELDNAME => array ('DAS_UID', 'OWNER_UID', 'OWNER_TYPE', ), + BasePeer::TYPE_NUM => array (0, 1, 2, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0 + */ + private static $fieldKeys = array ( + BasePeer::TYPE_PHPNAME => array ('DasUid' => 0, 'OwnerUid' => 1, 'OwnerType' => 2, ), + BasePeer::TYPE_COLNAME => array (DashboardDasIndPeer::DAS_UID => 0, DashboardDasIndPeer::OWNER_UID => 1, DashboardDasIndPeer::OWNER_TYPE => 2, ), + BasePeer::TYPE_FIELDNAME => array ('DAS_UID' => 0, 'OWNER_UID' => 1, 'OWNER_TYPE' => 2, ), + BasePeer::TYPE_NUM => array (0, 1, 2, ) + ); + + /** + * @return MapBuilder the map builder for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getMapBuilder() + { + include_once 'classes/model/map/DashboardDasIndMapBuilder.php'; + return BasePeer::getMapBuilder('classes.model.map.DashboardDasIndMapBuilder'); + } + /** + * Gets a map (hash) of PHP names to DB column names. + * + * @return array The PHP to DB name map for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @deprecated Use the getFieldNames() and translateFieldName() methods instead of this. + */ + public static function getPhpNameMap() + { + if (self::$phpNameMap === null) { + $map = DashboardDasIndPeer::getTableMap(); + $columns = $map->getColumns(); + $nameMap = array(); + foreach ($columns as $column) { + $nameMap[$column->getPhpName()] = $column->getColumnName(); + } + self::$phpNameMap = $nameMap; + } + return self::$phpNameMap; + } + /** + * Translates a fieldname to another type + * + * @param string $name field name + * @param string $fromType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @param string $toType One of the class type constants + * @return string translated name of the field. + */ + static public function translateFieldName($name, $fromType, $toType) + { + $toNames = self::getFieldNames($toType); + $key = isset(self::$fieldKeys[$fromType][$name]) ? self::$fieldKeys[$fromType][$name] : null; + if ($key === null) { + throw new PropelException("'$name' could not be found in the field names of type '$fromType'. These are: " . print_r(self::$fieldKeys[$fromType], true)); + } + return $toNames[$key]; + } + + /** + * Returns an array of of field names. + * + * @param string $type The type of fieldnames to return: + * One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return array A list of field names + */ + + static public function getFieldNames($type = BasePeer::TYPE_PHPNAME) + { + if (!array_key_exists($type, self::$fieldNames)) { + throw new PropelException('Method getFieldNames() expects the parameter $type to be one of the class constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM. ' . $type . ' was given.'); + } + return self::$fieldNames[$type]; + } + + /** + * Convenience method which changes table.column to alias.column. + * + * Using this method you can maintain SQL abstraction while using column aliases. + * + * $c->addAlias("alias1", TablePeer::TABLE_NAME); + * $c->addJoin(TablePeer::alias("alias1", TablePeer::PRIMARY_KEY_COLUMN), TablePeer::PRIMARY_KEY_COLUMN); + * + * @param string $alias The alias for the current table. + * @param string $column The column name for current table. (i.e. DashboardDasIndPeer::COLUMN_NAME). + * @return string + */ + public static function alias($alias, $column) + { + return str_replace(DashboardDasIndPeer::TABLE_NAME.'.', $alias.'.', $column); + } + + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param criteria object containing the columns to add. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria) + { + + $criteria->addSelectColumn(DashboardDasIndPeer::DAS_UID); + + $criteria->addSelectColumn(DashboardDasIndPeer::OWNER_UID); + + $criteria->addSelectColumn(DashboardDasIndPeer::OWNER_TYPE); + + } + + const COUNT = 'COUNT(DASHBOARD_DAS_IND.DAS_UID)'; + const COUNT_DISTINCT = 'COUNT(DISTINCT DASHBOARD_DAS_IND.DAS_UID)'; + + /** + * Returns the number of rows matching criteria. + * + * @param Criteria $criteria + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCount(Criteria $criteria, $distinct = false, $con = null) + { + // we're going to modify criteria, so copy it first + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(DashboardDasIndPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(DashboardDasIndPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach ($criteria->getGroupByColumns() as $column) { + $criteria->addSelectColumn($column); + } + + $rs = DashboardDasIndPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + /** + * Method to select one object from the DB. + * + * @param Criteria $criteria object used to create the SELECT statement. + * @param Connection $con + * @return DashboardDasInd + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectOne(Criteria $criteria, $con = null) + { + $critcopy = clone $criteria; + $critcopy->setLimit(1); + $objects = DashboardDasIndPeer::doSelect($critcopy, $con); + if ($objects) { + return $objects[0]; + } + return null; + } + /** + * Method to do selects. + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con + * @return array Array of selected Objects + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelect(Criteria $criteria, $con = null) + { + return DashboardDasIndPeer::populateObjects(DashboardDasIndPeer::doSelectRS($criteria, $con)); + } + /** + * Prepares the Criteria object and uses the parent doSelect() + * method to get a ResultSet. + * + * Use this method directly if you want to just get the resultset + * (instead of an array of objects). + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con the connection to use + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return ResultSet The resultset object with numerically-indexed fields. + * @see BasePeer::doSelect() + */ + public static function doSelectRS(Criteria $criteria, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if (!$criteria->getSelectColumns()) { + $criteria = clone $criteria; + DashboardDasIndPeer::addSelectColumns($criteria); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + // BasePeer returns a Creole ResultSet, set to return + // rows indexed numerically. + return BasePeer::doSelect($criteria, $con); + } + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(ResultSet $rs) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = DashboardDasIndPeer::getOMClass(); + $cls = Propel::import($cls); + // populate the object(s) + while ($rs->next()) { + + $obj = new $cls(); + $obj->hydrate($rs); + $results[] = $obj; + + } + return $results; + } + + /** + * Returns the number of rows matching criteria, joining the related Dashboard table + * + * @param Criteria $c + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCountJoinDashboard(Criteria $criteria, $distinct = false, $con = null) + { + // we're going to modify criteria, so copy it first + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(DashboardDasIndPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(DashboardDasIndPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach($criteria->getGroupByColumns() as $column) + { + $criteria->addSelectColumn($column); + } + + $criteria->addJoin(DashboardDasIndPeer::DAS_UID, DashboardPeer::DAS_UID); + + $rs = DashboardDasIndPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + + + /** + * Selects a collection of DashboardDasInd objects pre-filled with their Dashboard objects. + * + * @return array Array of DashboardDasInd objects. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectJoinDashboard(Criteria $c, $con = null) + { + $c = clone $c; + + // Set the correct dbName if it has not been overridden + if ($c->getDbName() == Propel::getDefaultDB()) { + $c->setDbName(self::DATABASE_NAME); + } + + DashboardDasIndPeer::addSelectColumns($c); + $startcol = (DashboardDasIndPeer::NUM_COLUMNS - DashboardDasIndPeer::NUM_LAZY_LOAD_COLUMNS) + 1; + DashboardPeer::addSelectColumns($c); + + $c->addJoin(DashboardDasIndPeer::DAS_UID, DashboardPeer::DAS_UID); + $rs = BasePeer::doSelect($c, $con); + $results = array(); + + while($rs->next()) { + + $omClass = DashboardDasIndPeer::getOMClass(); + + $cls = Propel::import($omClass); + $obj1 = new $cls(); + $obj1->hydrate($rs); + + $omClass = DashboardPeer::getOMClass(); + + $cls = Propel::import($omClass); + $obj2 = new $cls(); + $obj2->hydrate($rs, $startcol); + + $newObject = true; + foreach($results as $temp_obj1) { + $temp_obj2 = $temp_obj1->getDashboard(); //CHECKME + if ($temp_obj2->getPrimaryKey() === $obj2->getPrimaryKey()) { + $newObject = false; + // e.g. $author->addBookRelatedByBookId() + $temp_obj2->addDashboardDasInd($obj1); //CHECKME + break; + } + } + if ($newObject) { + $obj2->initDashboardDasInds(); + $obj2->addDashboardDasInd($obj1); //CHECKME + } + $results[] = $obj1; + } + return $results; + } + + + /** + * Returns the number of rows matching criteria, joining all related tables + * + * @param Criteria $c + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCountJoinAll(Criteria $criteria, $distinct = false, $con = null) + { + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(DashboardDasIndPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(DashboardDasIndPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach($criteria->getGroupByColumns() as $column) + { + $criteria->addSelectColumn($column); + } + + $criteria->addJoin(DashboardDasIndPeer::DAS_UID, DashboardPeer::DAS_UID); + + $rs = DashboardDasIndPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + + + /** + * Selects a collection of DashboardDasInd objects pre-filled with all related objects. + * + * @return array Array of DashboardDasInd objects. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectJoinAll(Criteria $c, $con = null) + { + $c = clone $c; + + // Set the correct dbName if it has not been overridden + if ($c->getDbName() == Propel::getDefaultDB()) { + $c->setDbName(self::DATABASE_NAME); + } + + DashboardDasIndPeer::addSelectColumns($c); + $startcol2 = (DashboardDasIndPeer::NUM_COLUMNS - DashboardDasIndPeer::NUM_LAZY_LOAD_COLUMNS) + 1; + + DashboardPeer::addSelectColumns($c); + $startcol3 = $startcol2 + DashboardPeer::NUM_COLUMNS; + + $c->addJoin(DashboardDasIndPeer::DAS_UID, DashboardPeer::DAS_UID); + + $rs = BasePeer::doSelect($c, $con); + $results = array(); + + while($rs->next()) { + + $omClass = DashboardDasIndPeer::getOMClass(); + + + $cls = Propel::import($omClass); + $obj1 = new $cls(); + $obj1->hydrate($rs); + + + // Add objects for joined Dashboard rows + + $omClass = DashboardPeer::getOMClass(); + + + $cls = Propel::import($omClass); + $obj2 = new $cls(); + $obj2->hydrate($rs, $startcol2); + + $newObject = true; + for ($j=0, $resCount=count($results); $j < $resCount; $j++) { + $temp_obj1 = $results[$j]; + $temp_obj2 = $temp_obj1->getDashboard(); // CHECKME + if ($temp_obj2->getPrimaryKey() === $obj2->getPrimaryKey()) { + $newObject = false; + $temp_obj2->addDashboardDasInd($obj1); // CHECKME + break; + } + } + + if ($newObject) { + $obj2->initDashboardDasInds(); + $obj2->addDashboardDasInd($obj1); + } + + $results[] = $obj1; + } + return $results; + } + + /** + * Returns the TableMap related to this peer. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getDatabaseMap(self::DATABASE_NAME)->getTable(self::TABLE_NAME); + } + + /** + * The class that the Peer will make instances of. + * + * This uses a dot-path notation which is tranalted into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @return string path.to.ClassName + */ + public static function getOMClass() + { + return DashboardDasIndPeer::CLASS_DEFAULT; + } + + /** + * Method perform an INSERT on the database, given a DashboardDasInd or Criteria object. + * + * @param mixed $values Criteria or DashboardDasInd object containing data that is used to create the INSERT statement. + * @param Connection $con the connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } else { + $criteria = $values->buildCriteria(); // build Criteria from DashboardDasInd object + } + + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->begin(); + $pk = BasePeer::doInsert($criteria, $con); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + + return $pk; + } + + /** + * Method perform an UPDATE on the database, given a DashboardDasInd or Criteria object. + * + * @param mixed $values Criteria or DashboardDasInd object containing data create the UPDATE statement. + * @param Connection $con The connection to use (specify Connection exert more control over transactions). + * @return int The number of affected rows (if supported by underlying database driver). + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doUpdate($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $selectCriteria = new Criteria(self::DATABASE_NAME); + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + + $comparison = $criteria->getComparison(DashboardDasIndPeer::DAS_UID); + $selectCriteria->add(DashboardDasIndPeer::DAS_UID, $criteria->remove(DashboardDasIndPeer::DAS_UID), $comparison); + + $comparison = $criteria->getComparison(DashboardDasIndPeer::OWNER_UID); + $selectCriteria->add(DashboardDasIndPeer::OWNER_UID, $criteria->remove(DashboardDasIndPeer::OWNER_UID), $comparison); + + } else { + $criteria = $values->buildCriteria(); // gets full criteria + $selectCriteria = $values->buildPkeyCriteria(); // gets criteria w/ primary key(s) + } + + // set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + return BasePeer::doUpdate($selectCriteria, $criteria, $con); + } + + /** + * Method to DELETE all rows from the DASHBOARD_DAS_IND table. + * + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll($con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + $affectedRows += BasePeer::doDeleteAll(DashboardDasIndPeer::TABLE_NAME, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Method perform a DELETE on the database, given a DashboardDasInd or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or DashboardDasInd object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param Connection $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + * This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(DashboardDasIndPeer::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } elseif ($values instanceof DashboardDasInd) { + + $criteria = $values->buildPkeyCriteria(); + } else { + // it must be the primary key + $criteria = new Criteria(self::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey + // values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + $vals = array(); + foreach ($values as $value) { + + $vals[0][] = $value[0]; + $vals[1][] = $value[1]; + } + + $criteria->add(DashboardDasIndPeer::DAS_UID, $vals[0], Criteria::IN); + $criteria->add(DashboardDasIndPeer::OWNER_UID, $vals[1], Criteria::IN); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + + $affectedRows += BasePeer::doDelete($criteria, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Validates all modified columns of given DashboardDasInd object. + * If parameter $columns is either a single column name or an array of column names + * than only those columns are validated. + * + * NOTICE: This does not apply to primary or foreign keys for now. + * + * @param DashboardDasInd $obj The object to validate. + * @param mixed $cols Column name or array of column names. + * + * @return mixed TRUE if all columns are valid or the error message of the first invalid column. + */ + public static function doValidate(DashboardDasInd $obj, $cols = null) + { + $columns = array(); + + if ($cols) { + $dbMap = Propel::getDatabaseMap(DashboardDasIndPeer::DATABASE_NAME); + $tableMap = $dbMap->getTable(DashboardDasIndPeer::TABLE_NAME); + + if (! is_array($cols)) { + $cols = array($cols); + } + + foreach ($cols as $colName) { + if ($tableMap->containsColumn($colName)) { + $get = 'get' . $tableMap->getColumn($colName)->getPhpName(); + $columns[$colName] = $obj->$get(); + } + } + } else { + + } + + return BasePeer::doValidate(DashboardDasIndPeer::DATABASE_NAME, DashboardDasIndPeer::TABLE_NAME, $columns); + } + + /** + * Retrieve object using using composite pkey values. + * @param string $das_uid + * @param string $owner_uid + * @param Connection $con + * @return DashboardDasInd + */ + public static function retrieveByPK($das_uid, $owner_uid, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $criteria = new Criteria(); + $criteria->add(DashboardDasIndPeer::DAS_UID, $das_uid); + $criteria->add(DashboardDasIndPeer::OWNER_UID, $owner_uid); + $v = DashboardDasIndPeer::doSelect($criteria, $con); + + return !empty($v) ? $v[0] : null; + } +} + + +// static code to register the map builder for this Peer with the main Propel class +if (Propel::isInit()) { + // the MapBuilder classes register themselves with Propel during initialization + // so we need to load them here. + try { + BaseDashboardDasIndPeer::getMapBuilder(); + } catch (Exception $e) { + Propel::log('Could not initialize Peer: ' . $e->getMessage(), Propel::LOG_ERR); + } +} else { + // even if Propel is not yet initialized, the map builder class can be registered + // now and then it will be loaded when Propel initializes. + require_once 'classes/model/map/DashboardDasIndMapBuilder.php'; + Propel::registerMapBuilder('classes.model.map.DashboardDasIndMapBuilder'); +} + diff --git a/workflow/engine/classes/model/om/BaseDashboardIndicator.php b/workflow/engine/classes/model/om/BaseDashboardIndicator.php new file mode 100644 index 000000000..4fac43561 --- /dev/null +++ b/workflow/engine/classes/model/om/BaseDashboardIndicator.php @@ -0,0 +1,1399 @@ +das_ind_uid; + } + + /** + * Get the [das_uid] column value. + * + * @return string + */ + public function getDasUid() + { + + return $this->das_uid; + } + + /** + * Get the [das_ind_type] column value. + * + * @return string + */ + public function getDasIndType() + { + + return $this->das_ind_type; + } + + /** + * Get the [das_ind_title] column value. + * + * @return string + */ + public function getDasIndTitle() + { + + return $this->das_ind_title; + } + + /** + * Get the [das_ind_goal] column value. + * + * @return double + */ + public function getDasIndGoal() + { + + return $this->das_ind_goal; + } + + /** + * Get the [das_ind_direction] column value. + * + * @return int + */ + public function getDasIndDirection() + { + + return $this->das_ind_direction; + } + + /** + * Get the [das_uid_process] column value. + * + * @return string + */ + public function getDasUidProcess() + { + + return $this->das_uid_process; + } + + /** + * Get the [das_ind_first_figure] column value. + * + * @return string + */ + public function getDasIndFirstFigure() + { + + return $this->das_ind_first_figure; + } + + /** + * Get the [das_ind_first_frequency] column value. + * + * @return string + */ + public function getDasIndFirstFrequency() + { + + return $this->das_ind_first_frequency; + } + + /** + * Get the [das_ind_second_figure] column value. + * + * @return string + */ + public function getDasIndSecondFigure() + { + + return $this->das_ind_second_figure; + } + + /** + * Get the [das_ind_second_frequency] column value. + * + * @return string + */ + public function getDasIndSecondFrequency() + { + + return $this->das_ind_second_frequency; + } + + /** + * Get the [optionally formatted] [das_ind_create_date] column value. + * + * @param string $format The date/time format string (either date()-style or strftime()-style). + * If format is NULL, then the integer unix timestamp will be returned. + * @return mixed Formatted date/time value as string or integer unix timestamp (if format is NULL). + * @throws PropelException - if unable to convert the date/time to timestamp. + */ + public function getDasIndCreateDate($format = 'Y-m-d H:i:s') + { + + if ($this->das_ind_create_date === null || $this->das_ind_create_date === '') { + return null; + } elseif (!is_int($this->das_ind_create_date)) { + // a non-timestamp value was set externally, so we convert it + $ts = strtotime($this->das_ind_create_date); + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse value of [das_ind_create_date] as date/time value: " . + var_export($this->das_ind_create_date, true)); + } + } else { + $ts = $this->das_ind_create_date; + } + if ($format === null) { + return $ts; + } elseif (strpos($format, '%') !== false) { + return strftime($format, $ts); + } else { + return date($format, $ts); + } + } + + /** + * Get the [optionally formatted] [das_ind_update_date] column value. + * + * @param string $format The date/time format string (either date()-style or strftime()-style). + * If format is NULL, then the integer unix timestamp will be returned. + * @return mixed Formatted date/time value as string or integer unix timestamp (if format is NULL). + * @throws PropelException - if unable to convert the date/time to timestamp. + */ + public function getDasIndUpdateDate($format = 'Y-m-d H:i:s') + { + + if ($this->das_ind_update_date === null || $this->das_ind_update_date === '') { + return null; + } elseif (!is_int($this->das_ind_update_date)) { + // a non-timestamp value was set externally, so we convert it + $ts = strtotime($this->das_ind_update_date); + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse value of [das_ind_update_date] as date/time value: " . + var_export($this->das_ind_update_date, true)); + } + } else { + $ts = $this->das_ind_update_date; + } + if ($format === null) { + return $ts; + } elseif (strpos($format, '%') !== false) { + return strftime($format, $ts); + } else { + return date($format, $ts); + } + } + + /** + * Get the [das_ind_status] column value. + * + * @return int + */ + public function getDasIndStatus() + { + + return $this->das_ind_status; + } + + /** + * Set the value of [das_ind_uid] column. + * + * @param string $v new value + * @return void + */ + public function setDasIndUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_ind_uid !== $v || $v === '') { + $this->das_ind_uid = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_UID; + } + + } // setDasIndUid() + + /** + * Set the value of [das_uid] column. + * + * @param string $v new value + * @return void + */ + public function setDasUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_uid !== $v || $v === '') { + $this->das_uid = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_UID; + } + + if ($this->aDashboard !== null && $this->aDashboard->getDasUid() !== $v) { + $this->aDashboard = null; + } + + } // setDasUid() + + /** + * Set the value of [das_ind_type] column. + * + * @param string $v new value + * @return void + */ + public function setDasIndType($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_ind_type !== $v || $v === '') { + $this->das_ind_type = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_TYPE; + } + + } // setDasIndType() + + /** + * Set the value of [das_ind_title] column. + * + * @param string $v new value + * @return void + */ + public function setDasIndTitle($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_ind_title !== $v || $v === '') { + $this->das_ind_title = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_TITLE; + } + + } // setDasIndTitle() + + /** + * Set the value of [das_ind_goal] column. + * + * @param double $v new value + * @return void + */ + public function setDasIndGoal($v) + { + + if ($this->das_ind_goal !== $v) { + $this->das_ind_goal = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_GOAL; + } + + } // setDasIndGoal() + + /** + * Set the value of [das_ind_direction] column. + * + * @param int $v new value + * @return void + */ + public function setDasIndDirection($v) + { + + // Since the native PHP type for this column is integer, + // we will cast the input value to an int (if it is not). + if ($v !== null && !is_int($v) && is_numeric($v)) { + $v = (int) $v; + } + + if ($this->das_ind_direction !== $v || $v === 2) { + $this->das_ind_direction = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_DIRECTION; + } + + } // setDasIndDirection() + + /** + * Set the value of [das_uid_process] column. + * + * @param string $v new value + * @return void + */ + public function setDasUidProcess($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_uid_process !== $v || $v === '') { + $this->das_uid_process = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_UID_PROCESS; + } + + } // setDasUidProcess() + + /** + * Set the value of [das_ind_first_figure] column. + * + * @param string $v new value + * @return void + */ + public function setDasIndFirstFigure($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_ind_first_figure !== $v || $v === '') { + $this->das_ind_first_figure = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_FIRST_FIGURE; + } + + } // setDasIndFirstFigure() + + /** + * Set the value of [das_ind_first_frequency] column. + * + * @param string $v new value + * @return void + */ + public function setDasIndFirstFrequency($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_ind_first_frequency !== $v || $v === '') { + $this->das_ind_first_frequency = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_FIRST_FREQUENCY; + } + + } // setDasIndFirstFrequency() + + /** + * Set the value of [das_ind_second_figure] column. + * + * @param string $v new value + * @return void + */ + public function setDasIndSecondFigure($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_ind_second_figure !== $v || $v === '') { + $this->das_ind_second_figure = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_SECOND_FIGURE; + } + + } // setDasIndSecondFigure() + + /** + * Set the value of [das_ind_second_frequency] column. + * + * @param string $v new value + * @return void + */ + public function setDasIndSecondFrequency($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->das_ind_second_frequency !== $v || $v === '') { + $this->das_ind_second_frequency = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_SECOND_FREQUENCY; + } + + } // setDasIndSecondFrequency() + + /** + * Set the value of [das_ind_create_date] column. + * + * @param int $v new value + * @return void + */ + public function setDasIndCreateDate($v) + { + + if ($v !== null && !is_int($v)) { + $ts = strtotime($v); + //Date/time accepts null values + if ($v == '') { + $ts = null; + } + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse date/time value for [das_ind_create_date] from input: " . + var_export($v, true)); + } + } else { + $ts = $v; + } + if ($this->das_ind_create_date !== $ts) { + $this->das_ind_create_date = $ts; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_CREATE_DATE; + } + + } // setDasIndCreateDate() + + /** + * Set the value of [das_ind_update_date] column. + * + * @param int $v new value + * @return void + */ + public function setDasIndUpdateDate($v) + { + + if ($v !== null && !is_int($v)) { + $ts = strtotime($v); + //Date/time accepts null values + if ($v == '') { + $ts = null; + } + if ($ts === -1 || $ts === false) { + throw new PropelException("Unable to parse date/time value for [das_ind_update_date] from input: " . + var_export($v, true)); + } + } else { + $ts = $v; + } + if ($this->das_ind_update_date !== $ts) { + $this->das_ind_update_date = $ts; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_UPDATE_DATE; + } + + } // setDasIndUpdateDate() + + /** + * Set the value of [das_ind_status] column. + * + * @param int $v new value + * @return void + */ + public function setDasIndStatus($v) + { + + // Since the native PHP type for this column is integer, + // we will cast the input value to an int (if it is not). + if ($v !== null && !is_int($v) && is_numeric($v)) { + $v = (int) $v; + } + + if ($this->das_ind_status !== $v || $v === 1) { + $this->das_ind_status = $v; + $this->modifiedColumns[] = DashboardIndicatorPeer::DAS_IND_STATUS; + } + + } // setDasIndStatus() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (1-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param ResultSet $rs The ResultSet class with cursor advanced to desired record pos. + * @param int $startcol 1-based offset column which indicates which restultset column to start with. + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate(ResultSet $rs, $startcol = 1) + { + try { + + $this->das_ind_uid = $rs->getString($startcol + 0); + + $this->das_uid = $rs->getString($startcol + 1); + + $this->das_ind_type = $rs->getString($startcol + 2); + + $this->das_ind_title = $rs->getString($startcol + 3); + + $this->das_ind_goal = $rs->getFloat($startcol + 4); + + $this->das_ind_direction = $rs->getInt($startcol + 5); + + $this->das_uid_process = $rs->getString($startcol + 6); + + $this->das_ind_first_figure = $rs->getString($startcol + 7); + + $this->das_ind_first_frequency = $rs->getString($startcol + 8); + + $this->das_ind_second_figure = $rs->getString($startcol + 9); + + $this->das_ind_second_frequency = $rs->getString($startcol + 10); + + $this->das_ind_create_date = $rs->getTimestamp($startcol + 11, null); + + $this->das_ind_update_date = $rs->getTimestamp($startcol + 12, null); + + $this->das_ind_status = $rs->getInt($startcol + 13); + + $this->resetModified(); + + $this->setNew(false); + + // FIXME - using NUM_COLUMNS may be clearer. + return $startcol + 14; // 14 = DashboardIndicatorPeer::NUM_COLUMNS - DashboardIndicatorPeer::NUM_LAZY_LOAD_COLUMNS). + + } catch (Exception $e) { + throw new PropelException("Error populating DashboardIndicator object", $e); + } + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param Connection $con + * @return void + * @throws PropelException + * @see BaseObject::setDeleted() + * @see BaseObject::isDeleted() + */ + public function delete($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(DashboardIndicatorPeer::DATABASE_NAME); + } + + try { + $con->begin(); + DashboardIndicatorPeer::doDelete($this, $con); + $this->setDeleted(true); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. If the object is new, + * it inserts it; otherwise an update is performed. This method + * wraps the doSave() worker method in a transaction. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update + * @throws PropelException + * @see doSave() + */ + public function save($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(DashboardIndicatorPeer::DATABASE_NAME); + } + + try { + $con->begin(); + $affectedRows = $this->doSave($con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update and any referring + * @throws PropelException + * @see save() + */ + protected function doSave($con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + + // We call the save method on the following object(s) if they + // were passed to this object by their coresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aDashboard !== null) { + if ($this->aDashboard->isModified()) { + $affectedRows += $this->aDashboard->save($con); + } + $this->setDashboard($this->aDashboard); + } + + + // If this object has been modified, then save it to the database. + if ($this->isModified()) { + if ($this->isNew()) { + $pk = DashboardIndicatorPeer::doInsert($this, $con); + $affectedRows += 1; // we are assuming that there is only 1 row per doInsert() which + // should always be true here (even though technically + // BasePeer::doInsert() can insert multiple rows). + + $this->setNew(false); + } else { + $affectedRows += DashboardIndicatorPeer::doUpdate($this, $con); + } + $this->resetModified(); // [HL] After being saved an object is no longer 'modified' + } + + $this->alreadyInSave = false; + } + return $affectedRows; + } // doSave() + + /** + * Array of ValidationFailed objects. + * @var array ValidationFailed[] + */ + protected $validationFailures = array(); + + /** + * Gets any ValidationFailed objects that resulted from last call to validate(). + * + * + * @return array ValidationFailed[] + * @see validate() + */ + public function getValidationFailures() + { + return $this->validationFailures; + } + + /** + * Validates the objects modified field values and all objects related to this table. + * + * If $columns is either a column name or an array of column names + * only those columns are validated. + * + * @param mixed $columns Column name or an array of column names. + * @return boolean Whether all columns pass validation. + * @see doValidate() + * @see getValidationFailures() + */ + public function validate($columns = null) + { + $res = $this->doValidate($columns); + if ($res === true) { + $this->validationFailures = array(); + return true; + } else { + $this->validationFailures = $res; + return false; + } + } + + /** + * This function performs the validation work for complex object models. + * + * In addition to checking the current object, all related objects will + * also be validated. If all pass then true is returned; otherwise + * an aggreagated array of ValidationFailed objects will be returned. + * + * @param array $columns Array of column names to validate. + * @return mixed true if all validations pass; + array of ValidationFailed objects otherwise. + */ + protected function doValidate($columns = null) + { + if (!$this->alreadyInValidation) { + $this->alreadyInValidation = true; + $retval = null; + + $failureMap = array(); + + + // We call the validate method on the following object(s) if they + // were passed to this object by their coresponding set + // method. This object relates to these object(s) by a + // foreign key reference. + + if ($this->aDashboard !== null) { + if (!$this->aDashboard->validate($columns)) { + $failureMap = array_merge($failureMap, $this->aDashboard->getValidationFailures()); + } + } + + + if (($retval = DashboardIndicatorPeer::doValidate($this, $columns)) !== true) { + $failureMap = array_merge($failureMap, $retval); + } + + + + $this->alreadyInValidation = false; + } + + return (!empty($failureMap) ? $failureMap : true); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return mixed Value of field. + */ + public function getByName($name, $type = BasePeer::TYPE_PHPNAME) + { + $pos = DashboardIndicatorPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->getByPosition($pos); + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch($pos) { + case 0: + return $this->getDasIndUid(); + break; + case 1: + return $this->getDasUid(); + break; + case 2: + return $this->getDasIndType(); + break; + case 3: + return $this->getDasIndTitle(); + break; + case 4: + return $this->getDasIndGoal(); + break; + case 5: + return $this->getDasIndDirection(); + break; + case 6: + return $this->getDasUidProcess(); + break; + case 7: + return $this->getDasIndFirstFigure(); + break; + case 8: + return $this->getDasIndFirstFrequency(); + break; + case 9: + return $this->getDasIndSecondFigure(); + break; + case 10: + return $this->getDasIndSecondFrequency(); + break; + case 11: + return $this->getDasIndCreateDate(); + break; + case 12: + return $this->getDasIndUpdateDate(); + break; + case 13: + return $this->getDasIndStatus(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = BasePeer::TYPE_PHPNAME) + { + $keys = DashboardIndicatorPeer::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getDasIndUid(), + $keys[1] => $this->getDasUid(), + $keys[2] => $this->getDasIndType(), + $keys[3] => $this->getDasIndTitle(), + $keys[4] => $this->getDasIndGoal(), + $keys[5] => $this->getDasIndDirection(), + $keys[6] => $this->getDasUidProcess(), + $keys[7] => $this->getDasIndFirstFigure(), + $keys[8] => $this->getDasIndFirstFrequency(), + $keys[9] => $this->getDasIndSecondFigure(), + $keys[10] => $this->getDasIndSecondFrequency(), + $keys[11] => $this->getDasIndCreateDate(), + $keys[12] => $this->getDasIndUpdateDate(), + $keys[13] => $this->getDasIndStatus(), + ); + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name peer name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return void + */ + public function setByName($name, $value, $type = BasePeer::TYPE_PHPNAME) + { + $pos = DashboardIndicatorPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch($pos) { + case 0: + $this->setDasIndUid($value); + break; + case 1: + $this->setDasUid($value); + break; + case 2: + $this->setDasIndType($value); + break; + case 3: + $this->setDasIndTitle($value); + break; + case 4: + $this->setDasIndGoal($value); + break; + case 5: + $this->setDasIndDirection($value); + break; + case 6: + $this->setDasUidProcess($value); + break; + case 7: + $this->setDasIndFirstFigure($value); + break; + case 8: + $this->setDasIndFirstFrequency($value); + break; + case 9: + $this->setDasIndSecondFigure($value); + break; + case 10: + $this->setDasIndSecondFrequency($value); + break; + case 11: + $this->setDasIndCreateDate($value); + break; + case 12: + $this->setDasIndUpdateDate($value); + break; + case 13: + $this->setDasIndStatus($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, + * TYPE_NUM. The default key type is the column's phpname (e.g. 'authorId') + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = BasePeer::TYPE_PHPNAME) + { + $keys = DashboardIndicatorPeer::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) { + $this->setDasIndUid($arr[$keys[0]]); + } + + if (array_key_exists($keys[1], $arr)) { + $this->setDasUid($arr[$keys[1]]); + } + + if (array_key_exists($keys[2], $arr)) { + $this->setDasIndType($arr[$keys[2]]); + } + + if (array_key_exists($keys[3], $arr)) { + $this->setDasIndTitle($arr[$keys[3]]); + } + + if (array_key_exists($keys[4], $arr)) { + $this->setDasIndGoal($arr[$keys[4]]); + } + + if (array_key_exists($keys[5], $arr)) { + $this->setDasIndDirection($arr[$keys[5]]); + } + + if (array_key_exists($keys[6], $arr)) { + $this->setDasUidProcess($arr[$keys[6]]); + } + + if (array_key_exists($keys[7], $arr)) { + $this->setDasIndFirstFigure($arr[$keys[7]]); + } + + if (array_key_exists($keys[8], $arr)) { + $this->setDasIndFirstFrequency($arr[$keys[8]]); + } + + if (array_key_exists($keys[9], $arr)) { + $this->setDasIndSecondFigure($arr[$keys[9]]); + } + + if (array_key_exists($keys[10], $arr)) { + $this->setDasIndSecondFrequency($arr[$keys[10]]); + } + + if (array_key_exists($keys[11], $arr)) { + $this->setDasIndCreateDate($arr[$keys[11]]); + } + + if (array_key_exists($keys[12], $arr)) { + $this->setDasIndUpdateDate($arr[$keys[12]]); + } + + if (array_key_exists($keys[13], $arr)) { + $this->setDasIndStatus($arr[$keys[13]]); + } + + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(DashboardIndicatorPeer::DATABASE_NAME); + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_UID)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_UID, $this->das_ind_uid); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_UID)) { + $criteria->add(DashboardIndicatorPeer::DAS_UID, $this->das_uid); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_TYPE)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_TYPE, $this->das_ind_type); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_TITLE)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_TITLE, $this->das_ind_title); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_GOAL)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_GOAL, $this->das_ind_goal); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_DIRECTION)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_DIRECTION, $this->das_ind_direction); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_UID_PROCESS)) { + $criteria->add(DashboardIndicatorPeer::DAS_UID_PROCESS, $this->das_uid_process); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_FIRST_FIGURE)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_FIRST_FIGURE, $this->das_ind_first_figure); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_FIRST_FREQUENCY)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_FIRST_FREQUENCY, $this->das_ind_first_frequency); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_SECOND_FIGURE)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_SECOND_FIGURE, $this->das_ind_second_figure); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_SECOND_FREQUENCY)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_SECOND_FREQUENCY, $this->das_ind_second_frequency); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_CREATE_DATE)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_CREATE_DATE, $this->das_ind_create_date); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_UPDATE_DATE)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_UPDATE_DATE, $this->das_ind_update_date); + } + + if ($this->isColumnModified(DashboardIndicatorPeer::DAS_IND_STATUS)) { + $criteria->add(DashboardIndicatorPeer::DAS_IND_STATUS, $this->das_ind_status); + } + + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(DashboardIndicatorPeer::DATABASE_NAME); + + $criteria->add(DashboardIndicatorPeer::DAS_IND_UID, $this->das_ind_uid); + + return $criteria; + } + + /** + * Returns the primary key for this object (row). + * @return string + */ + public function getPrimaryKey() + { + return $this->getDasIndUid(); + } + + /** + * Generic method to set the primary key (das_ind_uid column). + * + * @param string $key Primary key. + * @return void + */ + public function setPrimaryKey($key) + { + $this->setDasIndUid($key); + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of DashboardIndicator (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false) + { + + $copyObj->setDasUid($this->das_uid); + + $copyObj->setDasIndType($this->das_ind_type); + + $copyObj->setDasIndTitle($this->das_ind_title); + + $copyObj->setDasIndGoal($this->das_ind_goal); + + $copyObj->setDasIndDirection($this->das_ind_direction); + + $copyObj->setDasUidProcess($this->das_uid_process); + + $copyObj->setDasIndFirstFigure($this->das_ind_first_figure); + + $copyObj->setDasIndFirstFrequency($this->das_ind_first_frequency); + + $copyObj->setDasIndSecondFigure($this->das_ind_second_figure); + + $copyObj->setDasIndSecondFrequency($this->das_ind_second_frequency); + + $copyObj->setDasIndCreateDate($this->das_ind_create_date); + + $copyObj->setDasIndUpdateDate($this->das_ind_update_date); + + $copyObj->setDasIndStatus($this->das_ind_status); + + + $copyObj->setNew(true); + + $copyObj->setDasIndUid(''); // this is a pkey column, so set to default value + + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return DashboardIndicator Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + return $copyObj; + } + + /** + * Returns a peer instance associated with this om. + * + * Since Peer classes are not to have any instance attributes, this method returns the + * same instance for all member of this class. The method could therefore + * be static, but this would prevent one from overriding the behavior. + * + * @return DashboardIndicatorPeer + */ + public function getPeer() + { + if (self::$peer === null) { + self::$peer = new DashboardIndicatorPeer(); + } + return self::$peer; + } + + /** + * Declares an association between this object and a Dashboard object. + * + * @param Dashboard $v + * @return void + * @throws PropelException + */ + public function setDashboard($v) + { + + + if ($v === null) { + $this->setDasUid(''); + } else { + $this->setDasUid($v->getDasUid()); + } + + + $this->aDashboard = $v; + } + + + /** + * Get the associated Dashboard object + * + * @param Connection Optional Connection object. + * @return Dashboard The associated Dashboard object. + * @throws PropelException + */ + public function getDashboard($con = null) + { + // include the related Peer class + include_once 'classes/model/om/BaseDashboardPeer.php'; + + if ($this->aDashboard === null && (($this->das_uid !== "" && $this->das_uid !== null))) { + + $this->aDashboard = DashboardPeer::retrieveByPK($this->das_uid, $con); + + /* The following can be used instead of the line above to + guarantee the related object contains a reference + to this object, but this level of coupling + may be undesirable in many circumstances. + As it can lead to a db query with many results that may + never be used. + $obj = DashboardPeer::retrieveByPK($this->das_uid, $con); + $obj->addDashboards($this); + */ + } + return $this->aDashboard; + } +} + diff --git a/workflow/engine/classes/model/om/BaseDashboardIndicatorPeer.php b/workflow/engine/classes/model/om/BaseDashboardIndicatorPeer.php new file mode 100644 index 000000000..11e52f198 --- /dev/null +++ b/workflow/engine/classes/model/om/BaseDashboardIndicatorPeer.php @@ -0,0 +1,835 @@ + array ('DasIndUid', 'DasUid', 'DasIndType', 'DasIndTitle', 'DasIndGoal', 'DasIndDirection', 'DasUidProcess', 'DasIndFirstFigure', 'DasIndFirstFrequency', 'DasIndSecondFigure', 'DasIndSecondFrequency', 'DasIndCreateDate', 'DasIndUpdateDate', 'DasIndStatus', ), + BasePeer::TYPE_COLNAME => array (DashboardIndicatorPeer::DAS_IND_UID, DashboardIndicatorPeer::DAS_UID, DashboardIndicatorPeer::DAS_IND_TYPE, DashboardIndicatorPeer::DAS_IND_TITLE, DashboardIndicatorPeer::DAS_IND_GOAL, DashboardIndicatorPeer::DAS_IND_DIRECTION, DashboardIndicatorPeer::DAS_UID_PROCESS, DashboardIndicatorPeer::DAS_IND_FIRST_FIGURE, DashboardIndicatorPeer::DAS_IND_FIRST_FREQUENCY, DashboardIndicatorPeer::DAS_IND_SECOND_FIGURE, DashboardIndicatorPeer::DAS_IND_SECOND_FREQUENCY, DashboardIndicatorPeer::DAS_IND_CREATE_DATE, DashboardIndicatorPeer::DAS_IND_UPDATE_DATE, DashboardIndicatorPeer::DAS_IND_STATUS, ), + BasePeer::TYPE_FIELDNAME => array ('DAS_IND_UID', 'DAS_UID', 'DAS_IND_TYPE', 'DAS_IND_TITLE', 'DAS_IND_GOAL', 'DAS_IND_DIRECTION', 'DAS_UID_PROCESS', 'DAS_IND_FIRST_FIGURE', 'DAS_IND_FIRST_FREQUENCY', 'DAS_IND_SECOND_FIGURE', 'DAS_IND_SECOND_FREQUENCY', 'DAS_IND_CREATE_DATE', 'DAS_IND_UPDATE_DATE', 'DAS_IND_STATUS', ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0 + */ + private static $fieldKeys = array ( + BasePeer::TYPE_PHPNAME => array ('DasIndUid' => 0, 'DasUid' => 1, 'DasIndType' => 2, 'DasIndTitle' => 3, 'DasIndGoal' => 4, 'DasIndDirection' => 5, 'DasUidProcess' => 6, 'DasIndFirstFigure' => 7, 'DasIndFirstFrequency' => 8, 'DasIndSecondFigure' => 9, 'DasIndSecondFrequency' => 10, 'DasIndCreateDate' => 11, 'DasIndUpdateDate' => 12, 'DasIndStatus' => 13, ), + BasePeer::TYPE_COLNAME => array (DashboardIndicatorPeer::DAS_IND_UID => 0, DashboardIndicatorPeer::DAS_UID => 1, DashboardIndicatorPeer::DAS_IND_TYPE => 2, DashboardIndicatorPeer::DAS_IND_TITLE => 3, DashboardIndicatorPeer::DAS_IND_GOAL => 4, DashboardIndicatorPeer::DAS_IND_DIRECTION => 5, DashboardIndicatorPeer::DAS_UID_PROCESS => 6, DashboardIndicatorPeer::DAS_IND_FIRST_FIGURE => 7, DashboardIndicatorPeer::DAS_IND_FIRST_FREQUENCY => 8, DashboardIndicatorPeer::DAS_IND_SECOND_FIGURE => 9, DashboardIndicatorPeer::DAS_IND_SECOND_FREQUENCY => 10, DashboardIndicatorPeer::DAS_IND_CREATE_DATE => 11, DashboardIndicatorPeer::DAS_IND_UPDATE_DATE => 12, DashboardIndicatorPeer::DAS_IND_STATUS => 13, ), + BasePeer::TYPE_FIELDNAME => array ('DAS_IND_UID' => 0, 'DAS_UID' => 1, 'DAS_IND_TYPE' => 2, 'DAS_IND_TITLE' => 3, 'DAS_IND_GOAL' => 4, 'DAS_IND_DIRECTION' => 5, 'DAS_UID_PROCESS' => 6, 'DAS_IND_FIRST_FIGURE' => 7, 'DAS_IND_FIRST_FREQUENCY' => 8, 'DAS_IND_SECOND_FIGURE' => 9, 'DAS_IND_SECOND_FREQUENCY' => 10, 'DAS_IND_CREATE_DATE' => 11, 'DAS_IND_UPDATE_DATE' => 12, 'DAS_IND_STATUS' => 13, ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ) + ); + + /** + * @return MapBuilder the map builder for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getMapBuilder() + { + include_once 'classes/model/map/DashboardIndicatorMapBuilder.php'; + return BasePeer::getMapBuilder('classes.model.map.DashboardIndicatorMapBuilder'); + } + /** + * Gets a map (hash) of PHP names to DB column names. + * + * @return array The PHP to DB name map for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @deprecated Use the getFieldNames() and translateFieldName() methods instead of this. + */ + public static function getPhpNameMap() + { + if (self::$phpNameMap === null) { + $map = DashboardIndicatorPeer::getTableMap(); + $columns = $map->getColumns(); + $nameMap = array(); + foreach ($columns as $column) { + $nameMap[$column->getPhpName()] = $column->getColumnName(); + } + self::$phpNameMap = $nameMap; + } + return self::$phpNameMap; + } + /** + * Translates a fieldname to another type + * + * @param string $name field name + * @param string $fromType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @param string $toType One of the class type constants + * @return string translated name of the field. + */ + static public function translateFieldName($name, $fromType, $toType) + { + $toNames = self::getFieldNames($toType); + $key = isset(self::$fieldKeys[$fromType][$name]) ? self::$fieldKeys[$fromType][$name] : null; + if ($key === null) { + throw new PropelException("'$name' could not be found in the field names of type '$fromType'. These are: " . print_r(self::$fieldKeys[$fromType], true)); + } + return $toNames[$key]; + } + + /** + * Returns an array of of field names. + * + * @param string $type The type of fieldnames to return: + * One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return array A list of field names + */ + + static public function getFieldNames($type = BasePeer::TYPE_PHPNAME) + { + if (!array_key_exists($type, self::$fieldNames)) { + throw new PropelException('Method getFieldNames() expects the parameter $type to be one of the class constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM. ' . $type . ' was given.'); + } + return self::$fieldNames[$type]; + } + + /** + * Convenience method which changes table.column to alias.column. + * + * Using this method you can maintain SQL abstraction while using column aliases. + * + * $c->addAlias("alias1", TablePeer::TABLE_NAME); + * $c->addJoin(TablePeer::alias("alias1", TablePeer::PRIMARY_KEY_COLUMN), TablePeer::PRIMARY_KEY_COLUMN); + * + * @param string $alias The alias for the current table. + * @param string $column The column name for current table. (i.e. DashboardIndicatorPeer::COLUMN_NAME). + * @return string + */ + public static function alias($alias, $column) + { + return str_replace(DashboardIndicatorPeer::TABLE_NAME.'.', $alias.'.', $column); + } + + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param criteria object containing the columns to add. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria) + { + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_UID); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_UID); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_TYPE); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_TITLE); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_GOAL); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_DIRECTION); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_UID_PROCESS); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_FIRST_FIGURE); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_FIRST_FREQUENCY); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_SECOND_FIGURE); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_SECOND_FREQUENCY); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_CREATE_DATE); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_UPDATE_DATE); + + $criteria->addSelectColumn(DashboardIndicatorPeer::DAS_IND_STATUS); + + } + + const COUNT = 'COUNT(DASHBOARD_INDICATOR.DAS_IND_UID)'; + const COUNT_DISTINCT = 'COUNT(DISTINCT DASHBOARD_INDICATOR.DAS_IND_UID)'; + + /** + * Returns the number of rows matching criteria. + * + * @param Criteria $criteria + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCount(Criteria $criteria, $distinct = false, $con = null) + { + // we're going to modify criteria, so copy it first + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(DashboardIndicatorPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(DashboardIndicatorPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach ($criteria->getGroupByColumns() as $column) { + $criteria->addSelectColumn($column); + } + + $rs = DashboardIndicatorPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + /** + * Method to select one object from the DB. + * + * @param Criteria $criteria object used to create the SELECT statement. + * @param Connection $con + * @return DashboardIndicator + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectOne(Criteria $criteria, $con = null) + { + $critcopy = clone $criteria; + $critcopy->setLimit(1); + $objects = DashboardIndicatorPeer::doSelect($critcopy, $con); + if ($objects) { + return $objects[0]; + } + return null; + } + /** + * Method to do selects. + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con + * @return array Array of selected Objects + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelect(Criteria $criteria, $con = null) + { + return DashboardIndicatorPeer::populateObjects(DashboardIndicatorPeer::doSelectRS($criteria, $con)); + } + /** + * Prepares the Criteria object and uses the parent doSelect() + * method to get a ResultSet. + * + * Use this method directly if you want to just get the resultset + * (instead of an array of objects). + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con the connection to use + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return ResultSet The resultset object with numerically-indexed fields. + * @see BasePeer::doSelect() + */ + public static function doSelectRS(Criteria $criteria, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if (!$criteria->getSelectColumns()) { + $criteria = clone $criteria; + DashboardIndicatorPeer::addSelectColumns($criteria); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + // BasePeer returns a Creole ResultSet, set to return + // rows indexed numerically. + return BasePeer::doSelect($criteria, $con); + } + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(ResultSet $rs) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = DashboardIndicatorPeer::getOMClass(); + $cls = Propel::import($cls); + // populate the object(s) + while ($rs->next()) { + + $obj = new $cls(); + $obj->hydrate($rs); + $results[] = $obj; + + } + return $results; + } + + /** + * Returns the number of rows matching criteria, joining the related Dashboard table + * + * @param Criteria $c + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCountJoinDashboard(Criteria $criteria, $distinct = false, $con = null) + { + // we're going to modify criteria, so copy it first + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(DashboardIndicatorPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(DashboardIndicatorPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach($criteria->getGroupByColumns() as $column) + { + $criteria->addSelectColumn($column); + } + + $criteria->addJoin(DashboardIndicatorPeer::DAS_UID, DashboardPeer::DAS_UID); + + $rs = DashboardIndicatorPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + + + /** + * Selects a collection of DashboardIndicator objects pre-filled with their Dashboard objects. + * + * @return array Array of DashboardIndicator objects. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectJoinDashboard(Criteria $c, $con = null) + { + $c = clone $c; + + // Set the correct dbName if it has not been overridden + if ($c->getDbName() == Propel::getDefaultDB()) { + $c->setDbName(self::DATABASE_NAME); + } + + DashboardIndicatorPeer::addSelectColumns($c); + $startcol = (DashboardIndicatorPeer::NUM_COLUMNS - DashboardIndicatorPeer::NUM_LAZY_LOAD_COLUMNS) + 1; + DashboardPeer::addSelectColumns($c); + + $c->addJoin(DashboardIndicatorPeer::DAS_UID, DashboardPeer::DAS_UID); + $rs = BasePeer::doSelect($c, $con); + $results = array(); + + while($rs->next()) { + + $omClass = DashboardIndicatorPeer::getOMClass(); + + $cls = Propel::import($omClass); + $obj1 = new $cls(); + $obj1->hydrate($rs); + + $omClass = DashboardPeer::getOMClass(); + + $cls = Propel::import($omClass); + $obj2 = new $cls(); + $obj2->hydrate($rs, $startcol); + + $newObject = true; + foreach($results as $temp_obj1) { + $temp_obj2 = $temp_obj1->getDashboard(); //CHECKME + if ($temp_obj2->getPrimaryKey() === $obj2->getPrimaryKey()) { + $newObject = false; + // e.g. $author->addBookRelatedByBookId() + $temp_obj2->addDashboardIndicator($obj1); //CHECKME + break; + } + } + if ($newObject) { + $obj2->initDashboardIndicators(); + $obj2->addDashboardIndicator($obj1); //CHECKME + } + $results[] = $obj1; + } + return $results; + } + + + /** + * Returns the number of rows matching criteria, joining all related tables + * + * @param Criteria $c + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCountJoinAll(Criteria $criteria, $distinct = false, $con = null) + { + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(DashboardIndicatorPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(DashboardIndicatorPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach($criteria->getGroupByColumns() as $column) + { + $criteria->addSelectColumn($column); + } + + $criteria->addJoin(DashboardIndicatorPeer::DAS_UID, DashboardPeer::DAS_UID); + + $rs = DashboardIndicatorPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + + + /** + * Selects a collection of DashboardIndicator objects pre-filled with all related objects. + * + * @return array Array of DashboardIndicator objects. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectJoinAll(Criteria $c, $con = null) + { + $c = clone $c; + + // Set the correct dbName if it has not been overridden + if ($c->getDbName() == Propel::getDefaultDB()) { + $c->setDbName(self::DATABASE_NAME); + } + + DashboardIndicatorPeer::addSelectColumns($c); + $startcol2 = (DashboardIndicatorPeer::NUM_COLUMNS - DashboardIndicatorPeer::NUM_LAZY_LOAD_COLUMNS) + 1; + + DashboardPeer::addSelectColumns($c); + $startcol3 = $startcol2 + DashboardPeer::NUM_COLUMNS; + + $c->addJoin(DashboardIndicatorPeer::DAS_UID, DashboardPeer::DAS_UID); + + $rs = BasePeer::doSelect($c, $con); + $results = array(); + + while($rs->next()) { + + $omClass = DashboardIndicatorPeer::getOMClass(); + + + $cls = Propel::import($omClass); + $obj1 = new $cls(); + $obj1->hydrate($rs); + + + // Add objects for joined Dashboard rows + + $omClass = DashboardPeer::getOMClass(); + + + $cls = Propel::import($omClass); + $obj2 = new $cls(); + $obj2->hydrate($rs, $startcol2); + + $newObject = true; + for ($j=0, $resCount=count($results); $j < $resCount; $j++) { + $temp_obj1 = $results[$j]; + $temp_obj2 = $temp_obj1->getDashboard(); // CHECKME + if ($temp_obj2->getPrimaryKey() === $obj2->getPrimaryKey()) { + $newObject = false; + $temp_obj2->addDashboardIndicator($obj1); // CHECKME + break; + } + } + + if ($newObject) { + $obj2->initDashboardIndicators(); + $obj2->addDashboardIndicator($obj1); + } + + $results[] = $obj1; + } + return $results; + } + + /** + * Returns the TableMap related to this peer. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getDatabaseMap(self::DATABASE_NAME)->getTable(self::TABLE_NAME); + } + + /** + * The class that the Peer will make instances of. + * + * This uses a dot-path notation which is tranalted into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @return string path.to.ClassName + */ + public static function getOMClass() + { + return DashboardIndicatorPeer::CLASS_DEFAULT; + } + + /** + * Method perform an INSERT on the database, given a DashboardIndicator or Criteria object. + * + * @param mixed $values Criteria or DashboardIndicator object containing data that is used to create the INSERT statement. + * @param Connection $con the connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } else { + $criteria = $values->buildCriteria(); // build Criteria from DashboardIndicator object + } + + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->begin(); + $pk = BasePeer::doInsert($criteria, $con); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + + return $pk; + } + + /** + * Method perform an UPDATE on the database, given a DashboardIndicator or Criteria object. + * + * @param mixed $values Criteria or DashboardIndicator object containing data create the UPDATE statement. + * @param Connection $con The connection to use (specify Connection exert more control over transactions). + * @return int The number of affected rows (if supported by underlying database driver). + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doUpdate($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $selectCriteria = new Criteria(self::DATABASE_NAME); + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + + $comparison = $criteria->getComparison(DashboardIndicatorPeer::DAS_IND_UID); + $selectCriteria->add(DashboardIndicatorPeer::DAS_IND_UID, $criteria->remove(DashboardIndicatorPeer::DAS_IND_UID), $comparison); + + } else { + $criteria = $values->buildCriteria(); // gets full criteria + $selectCriteria = $values->buildPkeyCriteria(); // gets criteria w/ primary key(s) + } + + // set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + return BasePeer::doUpdate($selectCriteria, $criteria, $con); + } + + /** + * Method to DELETE all rows from the DASHBOARD_INDICATOR table. + * + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll($con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + $affectedRows += BasePeer::doDeleteAll(DashboardIndicatorPeer::TABLE_NAME, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Method perform a DELETE on the database, given a DashboardIndicator or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or DashboardIndicator object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param Connection $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + * This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(DashboardIndicatorPeer::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } elseif ($values instanceof DashboardIndicator) { + + $criteria = $values->buildPkeyCriteria(); + } else { + // it must be the primary key + $criteria = new Criteria(self::DATABASE_NAME); + $criteria->add(DashboardIndicatorPeer::DAS_IND_UID, (array) $values, Criteria::IN); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + + $affectedRows += BasePeer::doDelete($criteria, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Validates all modified columns of given DashboardIndicator object. + * If parameter $columns is either a single column name or an array of column names + * than only those columns are validated. + * + * NOTICE: This does not apply to primary or foreign keys for now. + * + * @param DashboardIndicator $obj The object to validate. + * @param mixed $cols Column name or array of column names. + * + * @return mixed TRUE if all columns are valid or the error message of the first invalid column. + */ + public static function doValidate(DashboardIndicator $obj, $cols = null) + { + $columns = array(); + + if ($cols) { + $dbMap = Propel::getDatabaseMap(DashboardIndicatorPeer::DATABASE_NAME); + $tableMap = $dbMap->getTable(DashboardIndicatorPeer::TABLE_NAME); + + if (! is_array($cols)) { + $cols = array($cols); + } + + foreach ($cols as $colName) { + if ($tableMap->containsColumn($colName)) { + $get = 'get' . $tableMap->getColumn($colName)->getPhpName(); + $columns[$colName] = $obj->$get(); + } + } + } else { + + } + + return BasePeer::doValidate(DashboardIndicatorPeer::DATABASE_NAME, DashboardIndicatorPeer::TABLE_NAME, $columns); + } + + /** + * Retrieve a single object by pkey. + * + * @param mixed $pk the primary key. + * @param Connection $con the connection to use + * @return DashboardIndicator + */ + public static function retrieveByPK($pk, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $criteria = new Criteria(DashboardIndicatorPeer::DATABASE_NAME); + + $criteria->add(DashboardIndicatorPeer::DAS_IND_UID, $pk); + + + $v = DashboardIndicatorPeer::doSelect($criteria, $con); + + return !empty($v) > 0 ? $v[0] : null; + } + + /** + * Retrieve multiple objects by pkey. + * + * @param array $pks List of primary keys + * @param Connection $con the connection to use + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function retrieveByPKs($pks, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $objs = null; + if (empty($pks)) { + $objs = array(); + } else { + $criteria = new Criteria(); + $criteria->add(DashboardIndicatorPeer::DAS_IND_UID, $pks, Criteria::IN); + $objs = DashboardIndicatorPeer::doSelect($criteria, $con); + } + return $objs; + } +} + + +// static code to register the map builder for this Peer with the main Propel class +if (Propel::isInit()) { + // the MapBuilder classes register themselves with Propel during initialization + // so we need to load them here. + try { + BaseDashboardIndicatorPeer::getMapBuilder(); + } catch (Exception $e) { + Propel::log('Could not initialize Peer: ' . $e->getMessage(), Propel::LOG_ERR); + } +} else { + // even if Propel is not yet initialized, the map builder class can be registered + // now and then it will be loaded when Propel initializes. + require_once 'classes/model/map/DashboardIndicatorMapBuilder.php'; + Propel::registerMapBuilder('classes.model.map.DashboardIndicatorMapBuilder'); +} + diff --git a/workflow/engine/classes/model/om/BaseDashboardPeer.php b/workflow/engine/classes/model/om/BaseDashboardPeer.php new file mode 100644 index 000000000..66944c1e3 --- /dev/null +++ b/workflow/engine/classes/model/om/BaseDashboardPeer.php @@ -0,0 +1,592 @@ + array ('DasUid', 'DasTitle', 'DasDescription', 'DasCreateDate', 'DasUpdateDate', 'DasStatus', ), + BasePeer::TYPE_COLNAME => array (DashboardPeer::DAS_UID, DashboardPeer::DAS_TITLE, DashboardPeer::DAS_DESCRIPTION, DashboardPeer::DAS_CREATE_DATE, DashboardPeer::DAS_UPDATE_DATE, DashboardPeer::DAS_STATUS, ), + BasePeer::TYPE_FIELDNAME => array ('DAS_UID', 'DAS_TITLE', 'DAS_DESCRIPTION', 'DAS_CREATE_DATE', 'DAS_UPDATE_DATE', 'DAS_STATUS', ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0 + */ + private static $fieldKeys = array ( + BasePeer::TYPE_PHPNAME => array ('DasUid' => 0, 'DasTitle' => 1, 'DasDescription' => 2, 'DasCreateDate' => 3, 'DasUpdateDate' => 4, 'DasStatus' => 5, ), + BasePeer::TYPE_COLNAME => array (DashboardPeer::DAS_UID => 0, DashboardPeer::DAS_TITLE => 1, DashboardPeer::DAS_DESCRIPTION => 2, DashboardPeer::DAS_CREATE_DATE => 3, DashboardPeer::DAS_UPDATE_DATE => 4, DashboardPeer::DAS_STATUS => 5, ), + BasePeer::TYPE_FIELDNAME => array ('DAS_UID' => 0, 'DAS_TITLE' => 1, 'DAS_DESCRIPTION' => 2, 'DAS_CREATE_DATE' => 3, 'DAS_UPDATE_DATE' => 4, 'DAS_STATUS' => 5, ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, ) + ); + + /** + * @return MapBuilder the map builder for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getMapBuilder() + { + include_once 'classes/model/map/DashboardMapBuilder.php'; + return BasePeer::getMapBuilder('classes.model.map.DashboardMapBuilder'); + } + /** + * Gets a map (hash) of PHP names to DB column names. + * + * @return array The PHP to DB name map for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @deprecated Use the getFieldNames() and translateFieldName() methods instead of this. + */ + public static function getPhpNameMap() + { + if (self::$phpNameMap === null) { + $map = DashboardPeer::getTableMap(); + $columns = $map->getColumns(); + $nameMap = array(); + foreach ($columns as $column) { + $nameMap[$column->getPhpName()] = $column->getColumnName(); + } + self::$phpNameMap = $nameMap; + } + return self::$phpNameMap; + } + /** + * Translates a fieldname to another type + * + * @param string $name field name + * @param string $fromType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @param string $toType One of the class type constants + * @return string translated name of the field. + */ + static public function translateFieldName($name, $fromType, $toType) + { + $toNames = self::getFieldNames($toType); + $key = isset(self::$fieldKeys[$fromType][$name]) ? self::$fieldKeys[$fromType][$name] : null; + if ($key === null) { + throw new PropelException("'$name' could not be found in the field names of type '$fromType'. These are: " . print_r(self::$fieldKeys[$fromType], true)); + } + return $toNames[$key]; + } + + /** + * Returns an array of of field names. + * + * @param string $type The type of fieldnames to return: + * One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return array A list of field names + */ + + static public function getFieldNames($type = BasePeer::TYPE_PHPNAME) + { + if (!array_key_exists($type, self::$fieldNames)) { + throw new PropelException('Method getFieldNames() expects the parameter $type to be one of the class constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM. ' . $type . ' was given.'); + } + return self::$fieldNames[$type]; + } + + /** + * Convenience method which changes table.column to alias.column. + * + * Using this method you can maintain SQL abstraction while using column aliases. + * + * $c->addAlias("alias1", TablePeer::TABLE_NAME); + * $c->addJoin(TablePeer::alias("alias1", TablePeer::PRIMARY_KEY_COLUMN), TablePeer::PRIMARY_KEY_COLUMN); + * + * @param string $alias The alias for the current table. + * @param string $column The column name for current table. (i.e. DashboardPeer::COLUMN_NAME). + * @return string + */ + public static function alias($alias, $column) + { + return str_replace(DashboardPeer::TABLE_NAME.'.', $alias.'.', $column); + } + + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param criteria object containing the columns to add. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria) + { + + $criteria->addSelectColumn(DashboardPeer::DAS_UID); + + $criteria->addSelectColumn(DashboardPeer::DAS_TITLE); + + $criteria->addSelectColumn(DashboardPeer::DAS_DESCRIPTION); + + $criteria->addSelectColumn(DashboardPeer::DAS_CREATE_DATE); + + $criteria->addSelectColumn(DashboardPeer::DAS_UPDATE_DATE); + + $criteria->addSelectColumn(DashboardPeer::DAS_STATUS); + + } + + const COUNT = 'COUNT(DASHBOARD.DAS_UID)'; + const COUNT_DISTINCT = 'COUNT(DISTINCT DASHBOARD.DAS_UID)'; + + /** + * Returns the number of rows matching criteria. + * + * @param Criteria $criteria + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCount(Criteria $criteria, $distinct = false, $con = null) + { + // we're going to modify criteria, so copy it first + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(DashboardPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(DashboardPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach ($criteria->getGroupByColumns() as $column) { + $criteria->addSelectColumn($column); + } + + $rs = DashboardPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + /** + * Method to select one object from the DB. + * + * @param Criteria $criteria object used to create the SELECT statement. + * @param Connection $con + * @return Dashboard + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectOne(Criteria $criteria, $con = null) + { + $critcopy = clone $criteria; + $critcopy->setLimit(1); + $objects = DashboardPeer::doSelect($critcopy, $con); + if ($objects) { + return $objects[0]; + } + return null; + } + /** + * Method to do selects. + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con + * @return array Array of selected Objects + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelect(Criteria $criteria, $con = null) + { + return DashboardPeer::populateObjects(DashboardPeer::doSelectRS($criteria, $con)); + } + /** + * Prepares the Criteria object and uses the parent doSelect() + * method to get a ResultSet. + * + * Use this method directly if you want to just get the resultset + * (instead of an array of objects). + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con the connection to use + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return ResultSet The resultset object with numerically-indexed fields. + * @see BasePeer::doSelect() + */ + public static function doSelectRS(Criteria $criteria, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if (!$criteria->getSelectColumns()) { + $criteria = clone $criteria; + DashboardPeer::addSelectColumns($criteria); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + // BasePeer returns a Creole ResultSet, set to return + // rows indexed numerically. + return BasePeer::doSelect($criteria, $con); + } + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(ResultSet $rs) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = DashboardPeer::getOMClass(); + $cls = Propel::import($cls); + // populate the object(s) + while ($rs->next()) { + + $obj = new $cls(); + $obj->hydrate($rs); + $results[] = $obj; + + } + return $results; + } + /** + * Returns the TableMap related to this peer. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getDatabaseMap(self::DATABASE_NAME)->getTable(self::TABLE_NAME); + } + + /** + * The class that the Peer will make instances of. + * + * This uses a dot-path notation which is tranalted into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @return string path.to.ClassName + */ + public static function getOMClass() + { + return DashboardPeer::CLASS_DEFAULT; + } + + /** + * Method perform an INSERT on the database, given a Dashboard or Criteria object. + * + * @param mixed $values Criteria or Dashboard object containing data that is used to create the INSERT statement. + * @param Connection $con the connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } else { + $criteria = $values->buildCriteria(); // build Criteria from Dashboard object + } + + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->begin(); + $pk = BasePeer::doInsert($criteria, $con); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + + return $pk; + } + + /** + * Method perform an UPDATE on the database, given a Dashboard or Criteria object. + * + * @param mixed $values Criteria or Dashboard object containing data create the UPDATE statement. + * @param Connection $con The connection to use (specify Connection exert more control over transactions). + * @return int The number of affected rows (if supported by underlying database driver). + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doUpdate($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $selectCriteria = new Criteria(self::DATABASE_NAME); + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + + $comparison = $criteria->getComparison(DashboardPeer::DAS_UID); + $selectCriteria->add(DashboardPeer::DAS_UID, $criteria->remove(DashboardPeer::DAS_UID), $comparison); + + } else { + $criteria = $values->buildCriteria(); // gets full criteria + $selectCriteria = $values->buildPkeyCriteria(); // gets criteria w/ primary key(s) + } + + // set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + return BasePeer::doUpdate($selectCriteria, $criteria, $con); + } + + /** + * Method to DELETE all rows from the DASHBOARD table. + * + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll($con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + $affectedRows += BasePeer::doDeleteAll(DashboardPeer::TABLE_NAME, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Method perform a DELETE on the database, given a Dashboard or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or Dashboard object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param Connection $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + * This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(DashboardPeer::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } elseif ($values instanceof Dashboard) { + + $criteria = $values->buildPkeyCriteria(); + } else { + // it must be the primary key + $criteria = new Criteria(self::DATABASE_NAME); + $criteria->add(DashboardPeer::DAS_UID, (array) $values, Criteria::IN); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + + $affectedRows += BasePeer::doDelete($criteria, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Validates all modified columns of given Dashboard object. + * If parameter $columns is either a single column name or an array of column names + * than only those columns are validated. + * + * NOTICE: This does not apply to primary or foreign keys for now. + * + * @param Dashboard $obj The object to validate. + * @param mixed $cols Column name or array of column names. + * + * @return mixed TRUE if all columns are valid or the error message of the first invalid column. + */ + public static function doValidate(Dashboard $obj, $cols = null) + { + $columns = array(); + + if ($cols) { + $dbMap = Propel::getDatabaseMap(DashboardPeer::DATABASE_NAME); + $tableMap = $dbMap->getTable(DashboardPeer::TABLE_NAME); + + if (! is_array($cols)) { + $cols = array($cols); + } + + foreach ($cols as $colName) { + if ($tableMap->containsColumn($colName)) { + $get = 'get' . $tableMap->getColumn($colName)->getPhpName(); + $columns[$colName] = $obj->$get(); + } + } + } else { + + } + + return BasePeer::doValidate(DashboardPeer::DATABASE_NAME, DashboardPeer::TABLE_NAME, $columns); + } + + /** + * Retrieve a single object by pkey. + * + * @param mixed $pk the primary key. + * @param Connection $con the connection to use + * @return Dashboard + */ + public static function retrieveByPK($pk, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $criteria = new Criteria(DashboardPeer::DATABASE_NAME); + + $criteria->add(DashboardPeer::DAS_UID, $pk); + + + $v = DashboardPeer::doSelect($criteria, $con); + + return !empty($v) > 0 ? $v[0] : null; + } + + /** + * Retrieve multiple objects by pkey. + * + * @param array $pks List of primary keys + * @param Connection $con the connection to use + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function retrieveByPKs($pks, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $objs = null; + if (empty($pks)) { + $objs = array(); + } else { + $criteria = new Criteria(); + $criteria->add(DashboardPeer::DAS_UID, $pks, Criteria::IN); + $objs = DashboardPeer::doSelect($criteria, $con); + } + return $objs; + } +} + + +// static code to register the map builder for this Peer with the main Propel class +if (Propel::isInit()) { + // the MapBuilder classes register themselves with Propel during initialization + // so we need to load them here. + try { + BaseDashboardPeer::getMapBuilder(); + } catch (Exception $e) { + Propel::log('Could not initialize Peer: ' . $e->getMessage(), Propel::LOG_ERR); + } +} else { + // even if Propel is not yet initialized, the map builder class can be registered + // now and then it will be loaded when Propel initializes. + require_once 'classes/model/map/DashboardMapBuilder.php'; + Propel::registerMapBuilder('classes.model.map.DashboardMapBuilder'); +} + diff --git a/workflow/engine/classes/model/om/BaseProReporting.php b/workflow/engine/classes/model/om/BaseProReporting.php new file mode 100644 index 000000000..fd4c169dd --- /dev/null +++ b/workflow/engine/classes/model/om/BaseProReporting.php @@ -0,0 +1,1111 @@ +pro_uid; + } + + /** + * Get the [month] column value. + * + * @return int + */ + public function getMonth() + { + + return $this->month; + } + + /** + * Get the [year] column value. + * + * @return int + */ + public function getYear() + { + + return $this->year; + } + + /** + * Get the [avg_time] column value. + * + * @return double + */ + public function getAvgTime() + { + + return $this->avg_time; + } + + /** + * Get the [sdv_time] column value. + * + * @return double + */ + public function getSdvTime() + { + + return $this->sdv_time; + } + + /** + * Get the [total_cases_in] column value. + * + * @return double + */ + public function getTotalCasesIn() + { + + return $this->total_cases_in; + } + + /** + * Get the [total_cases_out] column value. + * + * @return double + */ + public function getTotalCasesOut() + { + + return $this->total_cases_out; + } + + /** + * Get the [configured_process_time] column value. + * + * @return double + */ + public function getConfiguredProcessTime() + { + + return $this->configured_process_time; + } + + /** + * Get the [configured_process_cost] column value. + * + * @return double + */ + public function getConfiguredProcessCost() + { + + return $this->configured_process_cost; + } + + /** + * Get the [total_cases_open] column value. + * + * @return double + */ + public function getTotalCasesOpen() + { + + return $this->total_cases_open; + } + + /** + * Get the [total_cases_overdue] column value. + * + * @return double + */ + public function getTotalCasesOverdue() + { + + return $this->total_cases_overdue; + } + + /** + * Get the [total_cases_on_time] column value. + * + * @return double + */ + public function getTotalCasesOnTime() + { + + return $this->total_cases_on_time; + } + + /** + * Set the value of [pro_uid] column. + * + * @param string $v new value + * @return void + */ + public function setProUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->pro_uid !== $v) { + $this->pro_uid = $v; + $this->modifiedColumns[] = ProReportingPeer::PRO_UID; + } + + } // setProUid() + + /** + * Set the value of [month] column. + * + * @param int $v new value + * @return void + */ + public function setMonth($v) + { + + // Since the native PHP type for this column is integer, + // we will cast the input value to an int (if it is not). + if ($v !== null && !is_int($v) && is_numeric($v)) { + $v = (int) $v; + } + + if ($this->month !== $v || $v === 0) { + $this->month = $v; + $this->modifiedColumns[] = ProReportingPeer::MONTH; + } + + } // setMonth() + + /** + * Set the value of [year] column. + * + * @param int $v new value + * @return void + */ + public function setYear($v) + { + + // Since the native PHP type for this column is integer, + // we will cast the input value to an int (if it is not). + if ($v !== null && !is_int($v) && is_numeric($v)) { + $v = (int) $v; + } + + if ($this->year !== $v || $v === 0) { + $this->year = $v; + $this->modifiedColumns[] = ProReportingPeer::YEAR; + } + + } // setYear() + + /** + * Set the value of [avg_time] column. + * + * @param double $v new value + * @return void + */ + public function setAvgTime($v) + { + + if ($this->avg_time !== $v) { + $this->avg_time = $v; + $this->modifiedColumns[] = ProReportingPeer::AVG_TIME; + } + + } // setAvgTime() + + /** + * Set the value of [sdv_time] column. + * + * @param double $v new value + * @return void + */ + public function setSdvTime($v) + { + + if ($this->sdv_time !== $v) { + $this->sdv_time = $v; + $this->modifiedColumns[] = ProReportingPeer::SDV_TIME; + } + + } // setSdvTime() + + /** + * Set the value of [total_cases_in] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesIn($v) + { + + if ($this->total_cases_in !== $v) { + $this->total_cases_in = $v; + $this->modifiedColumns[] = ProReportingPeer::TOTAL_CASES_IN; + } + + } // setTotalCasesIn() + + /** + * Set the value of [total_cases_out] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesOut($v) + { + + if ($this->total_cases_out !== $v) { + $this->total_cases_out = $v; + $this->modifiedColumns[] = ProReportingPeer::TOTAL_CASES_OUT; + } + + } // setTotalCasesOut() + + /** + * Set the value of [configured_process_time] column. + * + * @param double $v new value + * @return void + */ + public function setConfiguredProcessTime($v) + { + + if ($this->configured_process_time !== $v) { + $this->configured_process_time = $v; + $this->modifiedColumns[] = ProReportingPeer::CONFIGURED_PROCESS_TIME; + } + + } // setConfiguredProcessTime() + + /** + * Set the value of [configured_process_cost] column. + * + * @param double $v new value + * @return void + */ + public function setConfiguredProcessCost($v) + { + + if ($this->configured_process_cost !== $v) { + $this->configured_process_cost = $v; + $this->modifiedColumns[] = ProReportingPeer::CONFIGURED_PROCESS_COST; + } + + } // setConfiguredProcessCost() + + /** + * Set the value of [total_cases_open] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesOpen($v) + { + + if ($this->total_cases_open !== $v) { + $this->total_cases_open = $v; + $this->modifiedColumns[] = ProReportingPeer::TOTAL_CASES_OPEN; + } + + } // setTotalCasesOpen() + + /** + * Set the value of [total_cases_overdue] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesOverdue($v) + { + + if ($this->total_cases_overdue !== $v) { + $this->total_cases_overdue = $v; + $this->modifiedColumns[] = ProReportingPeer::TOTAL_CASES_OVERDUE; + } + + } // setTotalCasesOverdue() + + /** + * Set the value of [total_cases_on_time] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesOnTime($v) + { + + if ($this->total_cases_on_time !== $v) { + $this->total_cases_on_time = $v; + $this->modifiedColumns[] = ProReportingPeer::TOTAL_CASES_ON_TIME; + } + + } // setTotalCasesOnTime() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (1-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param ResultSet $rs The ResultSet class with cursor advanced to desired record pos. + * @param int $startcol 1-based offset column which indicates which restultset column to start with. + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate(ResultSet $rs, $startcol = 1) + { + try { + + $this->pro_uid = $rs->getString($startcol + 0); + + $this->month = $rs->getInt($startcol + 1); + + $this->year = $rs->getInt($startcol + 2); + + $this->avg_time = $rs->getFloat($startcol + 3); + + $this->sdv_time = $rs->getFloat($startcol + 4); + + $this->total_cases_in = $rs->getFloat($startcol + 5); + + $this->total_cases_out = $rs->getFloat($startcol + 6); + + $this->configured_process_time = $rs->getFloat($startcol + 7); + + $this->configured_process_cost = $rs->getFloat($startcol + 8); + + $this->total_cases_open = $rs->getFloat($startcol + 9); + + $this->total_cases_overdue = $rs->getFloat($startcol + 10); + + $this->total_cases_on_time = $rs->getFloat($startcol + 11); + + $this->resetModified(); + + $this->setNew(false); + + // FIXME - using NUM_COLUMNS may be clearer. + return $startcol + 12; // 12 = ProReportingPeer::NUM_COLUMNS - ProReportingPeer::NUM_LAZY_LOAD_COLUMNS). + + } catch (Exception $e) { + throw new PropelException("Error populating ProReporting object", $e); + } + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param Connection $con + * @return void + * @throws PropelException + * @see BaseObject::setDeleted() + * @see BaseObject::isDeleted() + */ + public function delete($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(ProReportingPeer::DATABASE_NAME); + } + + try { + $con->begin(); + ProReportingPeer::doDelete($this, $con); + $this->setDeleted(true); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. If the object is new, + * it inserts it; otherwise an update is performed. This method + * wraps the doSave() worker method in a transaction. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update + * @throws PropelException + * @see doSave() + */ + public function save($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(ProReportingPeer::DATABASE_NAME); + } + + try { + $con->begin(); + $affectedRows = $this->doSave($con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update and any referring + * @throws PropelException + * @see save() + */ + protected function doSave($con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + + // If this object has been modified, then save it to the database. + if ($this->isModified()) { + if ($this->isNew()) { + $pk = ProReportingPeer::doInsert($this, $con); + $affectedRows += 1; // we are assuming that there is only 1 row per doInsert() which + // should always be true here (even though technically + // BasePeer::doInsert() can insert multiple rows). + + $this->setNew(false); + } else { + $affectedRows += ProReportingPeer::doUpdate($this, $con); + } + $this->resetModified(); // [HL] After being saved an object is no longer 'modified' + } + + $this->alreadyInSave = false; + } + return $affectedRows; + } // doSave() + + /** + * Array of ValidationFailed objects. + * @var array ValidationFailed[] + */ + protected $validationFailures = array(); + + /** + * Gets any ValidationFailed objects that resulted from last call to validate(). + * + * + * @return array ValidationFailed[] + * @see validate() + */ + public function getValidationFailures() + { + return $this->validationFailures; + } + + /** + * Validates the objects modified field values and all objects related to this table. + * + * If $columns is either a column name or an array of column names + * only those columns are validated. + * + * @param mixed $columns Column name or an array of column names. + * @return boolean Whether all columns pass validation. + * @see doValidate() + * @see getValidationFailures() + */ + public function validate($columns = null) + { + $res = $this->doValidate($columns); + if ($res === true) { + $this->validationFailures = array(); + return true; + } else { + $this->validationFailures = $res; + return false; + } + } + + /** + * This function performs the validation work for complex object models. + * + * In addition to checking the current object, all related objects will + * also be validated. If all pass then true is returned; otherwise + * an aggreagated array of ValidationFailed objects will be returned. + * + * @param array $columns Array of column names to validate. + * @return mixed true if all validations pass; + array of ValidationFailed objects otherwise. + */ + protected function doValidate($columns = null) + { + if (!$this->alreadyInValidation) { + $this->alreadyInValidation = true; + $retval = null; + + $failureMap = array(); + + + if (($retval = ProReportingPeer::doValidate($this, $columns)) !== true) { + $failureMap = array_merge($failureMap, $retval); + } + + + + $this->alreadyInValidation = false; + } + + return (!empty($failureMap) ? $failureMap : true); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return mixed Value of field. + */ + public function getByName($name, $type = BasePeer::TYPE_PHPNAME) + { + $pos = ProReportingPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->getByPosition($pos); + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch($pos) { + case 0: + return $this->getProUid(); + break; + case 1: + return $this->getMonth(); + break; + case 2: + return $this->getYear(); + break; + case 3: + return $this->getAvgTime(); + break; + case 4: + return $this->getSdvTime(); + break; + case 5: + return $this->getTotalCasesIn(); + break; + case 6: + return $this->getTotalCasesOut(); + break; + case 7: + return $this->getConfiguredProcessTime(); + break; + case 8: + return $this->getConfiguredProcessCost(); + break; + case 9: + return $this->getTotalCasesOpen(); + break; + case 10: + return $this->getTotalCasesOverdue(); + break; + case 11: + return $this->getTotalCasesOnTime(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = BasePeer::TYPE_PHPNAME) + { + $keys = ProReportingPeer::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getProUid(), + $keys[1] => $this->getMonth(), + $keys[2] => $this->getYear(), + $keys[3] => $this->getAvgTime(), + $keys[4] => $this->getSdvTime(), + $keys[5] => $this->getTotalCasesIn(), + $keys[6] => $this->getTotalCasesOut(), + $keys[7] => $this->getConfiguredProcessTime(), + $keys[8] => $this->getConfiguredProcessCost(), + $keys[9] => $this->getTotalCasesOpen(), + $keys[10] => $this->getTotalCasesOverdue(), + $keys[11] => $this->getTotalCasesOnTime(), + ); + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name peer name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return void + */ + public function setByName($name, $value, $type = BasePeer::TYPE_PHPNAME) + { + $pos = ProReportingPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch($pos) { + case 0: + $this->setProUid($value); + break; + case 1: + $this->setMonth($value); + break; + case 2: + $this->setYear($value); + break; + case 3: + $this->setAvgTime($value); + break; + case 4: + $this->setSdvTime($value); + break; + case 5: + $this->setTotalCasesIn($value); + break; + case 6: + $this->setTotalCasesOut($value); + break; + case 7: + $this->setConfiguredProcessTime($value); + break; + case 8: + $this->setConfiguredProcessCost($value); + break; + case 9: + $this->setTotalCasesOpen($value); + break; + case 10: + $this->setTotalCasesOverdue($value); + break; + case 11: + $this->setTotalCasesOnTime($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, + * TYPE_NUM. The default key type is the column's phpname (e.g. 'authorId') + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = BasePeer::TYPE_PHPNAME) + { + $keys = ProReportingPeer::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) { + $this->setProUid($arr[$keys[0]]); + } + + if (array_key_exists($keys[1], $arr)) { + $this->setMonth($arr[$keys[1]]); + } + + if (array_key_exists($keys[2], $arr)) { + $this->setYear($arr[$keys[2]]); + } + + if (array_key_exists($keys[3], $arr)) { + $this->setAvgTime($arr[$keys[3]]); + } + + if (array_key_exists($keys[4], $arr)) { + $this->setSdvTime($arr[$keys[4]]); + } + + if (array_key_exists($keys[5], $arr)) { + $this->setTotalCasesIn($arr[$keys[5]]); + } + + if (array_key_exists($keys[6], $arr)) { + $this->setTotalCasesOut($arr[$keys[6]]); + } + + if (array_key_exists($keys[7], $arr)) { + $this->setConfiguredProcessTime($arr[$keys[7]]); + } + + if (array_key_exists($keys[8], $arr)) { + $this->setConfiguredProcessCost($arr[$keys[8]]); + } + + if (array_key_exists($keys[9], $arr)) { + $this->setTotalCasesOpen($arr[$keys[9]]); + } + + if (array_key_exists($keys[10], $arr)) { + $this->setTotalCasesOverdue($arr[$keys[10]]); + } + + if (array_key_exists($keys[11], $arr)) { + $this->setTotalCasesOnTime($arr[$keys[11]]); + } + + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(ProReportingPeer::DATABASE_NAME); + + if ($this->isColumnModified(ProReportingPeer::PRO_UID)) { + $criteria->add(ProReportingPeer::PRO_UID, $this->pro_uid); + } + + if ($this->isColumnModified(ProReportingPeer::MONTH)) { + $criteria->add(ProReportingPeer::MONTH, $this->month); + } + + if ($this->isColumnModified(ProReportingPeer::YEAR)) { + $criteria->add(ProReportingPeer::YEAR, $this->year); + } + + if ($this->isColumnModified(ProReportingPeer::AVG_TIME)) { + $criteria->add(ProReportingPeer::AVG_TIME, $this->avg_time); + } + + if ($this->isColumnModified(ProReportingPeer::SDV_TIME)) { + $criteria->add(ProReportingPeer::SDV_TIME, $this->sdv_time); + } + + if ($this->isColumnModified(ProReportingPeer::TOTAL_CASES_IN)) { + $criteria->add(ProReportingPeer::TOTAL_CASES_IN, $this->total_cases_in); + } + + if ($this->isColumnModified(ProReportingPeer::TOTAL_CASES_OUT)) { + $criteria->add(ProReportingPeer::TOTAL_CASES_OUT, $this->total_cases_out); + } + + if ($this->isColumnModified(ProReportingPeer::CONFIGURED_PROCESS_TIME)) { + $criteria->add(ProReportingPeer::CONFIGURED_PROCESS_TIME, $this->configured_process_time); + } + + if ($this->isColumnModified(ProReportingPeer::CONFIGURED_PROCESS_COST)) { + $criteria->add(ProReportingPeer::CONFIGURED_PROCESS_COST, $this->configured_process_cost); + } + + if ($this->isColumnModified(ProReportingPeer::TOTAL_CASES_OPEN)) { + $criteria->add(ProReportingPeer::TOTAL_CASES_OPEN, $this->total_cases_open); + } + + if ($this->isColumnModified(ProReportingPeer::TOTAL_CASES_OVERDUE)) { + $criteria->add(ProReportingPeer::TOTAL_CASES_OVERDUE, $this->total_cases_overdue); + } + + if ($this->isColumnModified(ProReportingPeer::TOTAL_CASES_ON_TIME)) { + $criteria->add(ProReportingPeer::TOTAL_CASES_ON_TIME, $this->total_cases_on_time); + } + + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(ProReportingPeer::DATABASE_NAME); + + $criteria->add(ProReportingPeer::PRO_UID, $this->pro_uid); + $criteria->add(ProReportingPeer::MONTH, $this->month); + $criteria->add(ProReportingPeer::YEAR, $this->year); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + + $pks[0] = $this->getProUid(); + + $pks[1] = $this->getMonth(); + + $pks[2] = $this->getYear(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + + $this->setProUid($keys[0]); + + $this->setMonth($keys[1]); + + $this->setYear($keys[2]); + + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of ProReporting (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false) + { + + $copyObj->setAvgTime($this->avg_time); + + $copyObj->setSdvTime($this->sdv_time); + + $copyObj->setTotalCasesIn($this->total_cases_in); + + $copyObj->setTotalCasesOut($this->total_cases_out); + + $copyObj->setConfiguredProcessTime($this->configured_process_time); + + $copyObj->setConfiguredProcessCost($this->configured_process_cost); + + $copyObj->setTotalCasesOpen($this->total_cases_open); + + $copyObj->setTotalCasesOverdue($this->total_cases_overdue); + + $copyObj->setTotalCasesOnTime($this->total_cases_on_time); + + + $copyObj->setNew(true); + + $copyObj->setProUid(NULL); // this is a pkey column, so set to default value + + $copyObj->setMonth('0'); // this is a pkey column, so set to default value + + $copyObj->setYear('0'); // this is a pkey column, so set to default value + + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return ProReporting Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + return $copyObj; + } + + /** + * Returns a peer instance associated with this om. + * + * Since Peer classes are not to have any instance attributes, this method returns the + * same instance for all member of this class. The method could therefore + * be static, but this would prevent one from overriding the behavior. + * + * @return ProReportingPeer + */ + public function getPeer() + { + if (self::$peer === null) { + self::$peer = new ProReportingPeer(); + } + return self::$peer; + } +} + diff --git a/workflow/engine/classes/model/om/BaseProReportingPeer.php b/workflow/engine/classes/model/om/BaseProReportingPeer.php new file mode 100644 index 000000000..ec30c449c --- /dev/null +++ b/workflow/engine/classes/model/om/BaseProReportingPeer.php @@ -0,0 +1,619 @@ + array ('ProUid', 'Month', 'Year', 'AvgTime', 'SdvTime', 'TotalCasesIn', 'TotalCasesOut', 'ConfiguredProcessTime', 'ConfiguredProcessCost', 'TotalCasesOpen', 'TotalCasesOverdue', 'TotalCasesOnTime', ), + BasePeer::TYPE_COLNAME => array (ProReportingPeer::PRO_UID, ProReportingPeer::MONTH, ProReportingPeer::YEAR, ProReportingPeer::AVG_TIME, ProReportingPeer::SDV_TIME, ProReportingPeer::TOTAL_CASES_IN, ProReportingPeer::TOTAL_CASES_OUT, ProReportingPeer::CONFIGURED_PROCESS_TIME, ProReportingPeer::CONFIGURED_PROCESS_COST, ProReportingPeer::TOTAL_CASES_OPEN, ProReportingPeer::TOTAL_CASES_OVERDUE, ProReportingPeer::TOTAL_CASES_ON_TIME, ), + BasePeer::TYPE_FIELDNAME => array ('PRO_UID', 'MONTH', 'YEAR', 'AVG_TIME', 'SDV_TIME', 'TOTAL_CASES_IN', 'TOTAL_CASES_OUT', 'CONFIGURED_PROCESS_TIME', 'CONFIGURED_PROCESS_COST', 'TOTAL_CASES_OPEN', 'TOTAL_CASES_OVERDUE', 'TOTAL_CASES_ON_TIME', ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0 + */ + private static $fieldKeys = array ( + BasePeer::TYPE_PHPNAME => array ('ProUid' => 0, 'Month' => 1, 'Year' => 2, 'AvgTime' => 3, 'SdvTime' => 4, 'TotalCasesIn' => 5, 'TotalCasesOut' => 6, 'ConfiguredProcessTime' => 7, 'ConfiguredProcessCost' => 8, 'TotalCasesOpen' => 9, 'TotalCasesOverdue' => 10, 'TotalCasesOnTime' => 11, ), + BasePeer::TYPE_COLNAME => array (ProReportingPeer::PRO_UID => 0, ProReportingPeer::MONTH => 1, ProReportingPeer::YEAR => 2, ProReportingPeer::AVG_TIME => 3, ProReportingPeer::SDV_TIME => 4, ProReportingPeer::TOTAL_CASES_IN => 5, ProReportingPeer::TOTAL_CASES_OUT => 6, ProReportingPeer::CONFIGURED_PROCESS_TIME => 7, ProReportingPeer::CONFIGURED_PROCESS_COST => 8, ProReportingPeer::TOTAL_CASES_OPEN => 9, ProReportingPeer::TOTAL_CASES_OVERDUE => 10, ProReportingPeer::TOTAL_CASES_ON_TIME => 11, ), + BasePeer::TYPE_FIELDNAME => array ('PRO_UID' => 0, 'MONTH' => 1, 'YEAR' => 2, 'AVG_TIME' => 3, 'SDV_TIME' => 4, 'TOTAL_CASES_IN' => 5, 'TOTAL_CASES_OUT' => 6, 'CONFIGURED_PROCESS_TIME' => 7, 'CONFIGURED_PROCESS_COST' => 8, 'TOTAL_CASES_OPEN' => 9, 'TOTAL_CASES_OVERDUE' => 10, 'TOTAL_CASES_ON_TIME' => 11, ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ) + ); + + /** + * @return MapBuilder the map builder for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getMapBuilder() + { + include_once 'classes/model/map/ProReportingMapBuilder.php'; + return BasePeer::getMapBuilder('classes.model.map.ProReportingMapBuilder'); + } + /** + * Gets a map (hash) of PHP names to DB column names. + * + * @return array The PHP to DB name map for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @deprecated Use the getFieldNames() and translateFieldName() methods instead of this. + */ + public static function getPhpNameMap() + { + if (self::$phpNameMap === null) { + $map = ProReportingPeer::getTableMap(); + $columns = $map->getColumns(); + $nameMap = array(); + foreach ($columns as $column) { + $nameMap[$column->getPhpName()] = $column->getColumnName(); + } + self::$phpNameMap = $nameMap; + } + return self::$phpNameMap; + } + /** + * Translates a fieldname to another type + * + * @param string $name field name + * @param string $fromType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @param string $toType One of the class type constants + * @return string translated name of the field. + */ + static public function translateFieldName($name, $fromType, $toType) + { + $toNames = self::getFieldNames($toType); + $key = isset(self::$fieldKeys[$fromType][$name]) ? self::$fieldKeys[$fromType][$name] : null; + if ($key === null) { + throw new PropelException("'$name' could not be found in the field names of type '$fromType'. These are: " . print_r(self::$fieldKeys[$fromType], true)); + } + return $toNames[$key]; + } + + /** + * Returns an array of of field names. + * + * @param string $type The type of fieldnames to return: + * One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return array A list of field names + */ + + static public function getFieldNames($type = BasePeer::TYPE_PHPNAME) + { + if (!array_key_exists($type, self::$fieldNames)) { + throw new PropelException('Method getFieldNames() expects the parameter $type to be one of the class constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM. ' . $type . ' was given.'); + } + return self::$fieldNames[$type]; + } + + /** + * Convenience method which changes table.column to alias.column. + * + * Using this method you can maintain SQL abstraction while using column aliases. + * + * $c->addAlias("alias1", TablePeer::TABLE_NAME); + * $c->addJoin(TablePeer::alias("alias1", TablePeer::PRIMARY_KEY_COLUMN), TablePeer::PRIMARY_KEY_COLUMN); + * + * @param string $alias The alias for the current table. + * @param string $column The column name for current table. (i.e. ProReportingPeer::COLUMN_NAME). + * @return string + */ + public static function alias($alias, $column) + { + return str_replace(ProReportingPeer::TABLE_NAME.'.', $alias.'.', $column); + } + + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param criteria object containing the columns to add. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria) + { + + $criteria->addSelectColumn(ProReportingPeer::PRO_UID); + + $criteria->addSelectColumn(ProReportingPeer::MONTH); + + $criteria->addSelectColumn(ProReportingPeer::YEAR); + + $criteria->addSelectColumn(ProReportingPeer::AVG_TIME); + + $criteria->addSelectColumn(ProReportingPeer::SDV_TIME); + + $criteria->addSelectColumn(ProReportingPeer::TOTAL_CASES_IN); + + $criteria->addSelectColumn(ProReportingPeer::TOTAL_CASES_OUT); + + $criteria->addSelectColumn(ProReportingPeer::CONFIGURED_PROCESS_TIME); + + $criteria->addSelectColumn(ProReportingPeer::CONFIGURED_PROCESS_COST); + + $criteria->addSelectColumn(ProReportingPeer::TOTAL_CASES_OPEN); + + $criteria->addSelectColumn(ProReportingPeer::TOTAL_CASES_OVERDUE); + + $criteria->addSelectColumn(ProReportingPeer::TOTAL_CASES_ON_TIME); + + } + + const COUNT = 'COUNT(PRO_REPORTING.PRO_UID)'; + const COUNT_DISTINCT = 'COUNT(DISTINCT PRO_REPORTING.PRO_UID)'; + + /** + * Returns the number of rows matching criteria. + * + * @param Criteria $criteria + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCount(Criteria $criteria, $distinct = false, $con = null) + { + // we're going to modify criteria, so copy it first + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(ProReportingPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(ProReportingPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach ($criteria->getGroupByColumns() as $column) { + $criteria->addSelectColumn($column); + } + + $rs = ProReportingPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + /** + * Method to select one object from the DB. + * + * @param Criteria $criteria object used to create the SELECT statement. + * @param Connection $con + * @return ProReporting + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectOne(Criteria $criteria, $con = null) + { + $critcopy = clone $criteria; + $critcopy->setLimit(1); + $objects = ProReportingPeer::doSelect($critcopy, $con); + if ($objects) { + return $objects[0]; + } + return null; + } + /** + * Method to do selects. + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con + * @return array Array of selected Objects + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelect(Criteria $criteria, $con = null) + { + return ProReportingPeer::populateObjects(ProReportingPeer::doSelectRS($criteria, $con)); + } + /** + * Prepares the Criteria object and uses the parent doSelect() + * method to get a ResultSet. + * + * Use this method directly if you want to just get the resultset + * (instead of an array of objects). + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con the connection to use + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return ResultSet The resultset object with numerically-indexed fields. + * @see BasePeer::doSelect() + */ + public static function doSelectRS(Criteria $criteria, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if (!$criteria->getSelectColumns()) { + $criteria = clone $criteria; + ProReportingPeer::addSelectColumns($criteria); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + // BasePeer returns a Creole ResultSet, set to return + // rows indexed numerically. + return BasePeer::doSelect($criteria, $con); + } + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(ResultSet $rs) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = ProReportingPeer::getOMClass(); + $cls = Propel::import($cls); + // populate the object(s) + while ($rs->next()) { + + $obj = new $cls(); + $obj->hydrate($rs); + $results[] = $obj; + + } + return $results; + } + /** + * Returns the TableMap related to this peer. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getDatabaseMap(self::DATABASE_NAME)->getTable(self::TABLE_NAME); + } + + /** + * The class that the Peer will make instances of. + * + * This uses a dot-path notation which is tranalted into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @return string path.to.ClassName + */ + public static function getOMClass() + { + return ProReportingPeer::CLASS_DEFAULT; + } + + /** + * Method perform an INSERT on the database, given a ProReporting or Criteria object. + * + * @param mixed $values Criteria or ProReporting object containing data that is used to create the INSERT statement. + * @param Connection $con the connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } else { + $criteria = $values->buildCriteria(); // build Criteria from ProReporting object + } + + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->begin(); + $pk = BasePeer::doInsert($criteria, $con); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + + return $pk; + } + + /** + * Method perform an UPDATE on the database, given a ProReporting or Criteria object. + * + * @param mixed $values Criteria or ProReporting object containing data create the UPDATE statement. + * @param Connection $con The connection to use (specify Connection exert more control over transactions). + * @return int The number of affected rows (if supported by underlying database driver). + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doUpdate($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $selectCriteria = new Criteria(self::DATABASE_NAME); + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + + $comparison = $criteria->getComparison(ProReportingPeer::PRO_UID); + $selectCriteria->add(ProReportingPeer::PRO_UID, $criteria->remove(ProReportingPeer::PRO_UID), $comparison); + + $comparison = $criteria->getComparison(ProReportingPeer::MONTH); + $selectCriteria->add(ProReportingPeer::MONTH, $criteria->remove(ProReportingPeer::MONTH), $comparison); + + $comparison = $criteria->getComparison(ProReportingPeer::YEAR); + $selectCriteria->add(ProReportingPeer::YEAR, $criteria->remove(ProReportingPeer::YEAR), $comparison); + + } else { + $criteria = $values->buildCriteria(); // gets full criteria + $selectCriteria = $values->buildPkeyCriteria(); // gets criteria w/ primary key(s) + } + + // set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + return BasePeer::doUpdate($selectCriteria, $criteria, $con); + } + + /** + * Method to DELETE all rows from the PRO_REPORTING table. + * + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll($con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + $affectedRows += BasePeer::doDeleteAll(ProReportingPeer::TABLE_NAME, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Method perform a DELETE on the database, given a ProReporting or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or ProReporting object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param Connection $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + * This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(ProReportingPeer::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } elseif ($values instanceof ProReporting) { + + $criteria = $values->buildPkeyCriteria(); + } else { + // it must be the primary key + $criteria = new Criteria(self::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey + // values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + $vals = array(); + foreach ($values as $value) { + + $vals[0][] = $value[0]; + $vals[1][] = $value[1]; + $vals[2][] = $value[2]; + } + + $criteria->add(ProReportingPeer::PRO_UID, $vals[0], Criteria::IN); + $criteria->add(ProReportingPeer::MONTH, $vals[1], Criteria::IN); + $criteria->add(ProReportingPeer::YEAR, $vals[2], Criteria::IN); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + + $affectedRows += BasePeer::doDelete($criteria, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Validates all modified columns of given ProReporting object. + * If parameter $columns is either a single column name or an array of column names + * than only those columns are validated. + * + * NOTICE: This does not apply to primary or foreign keys for now. + * + * @param ProReporting $obj The object to validate. + * @param mixed $cols Column name or array of column names. + * + * @return mixed TRUE if all columns are valid or the error message of the first invalid column. + */ + public static function doValidate(ProReporting $obj, $cols = null) + { + $columns = array(); + + if ($cols) { + $dbMap = Propel::getDatabaseMap(ProReportingPeer::DATABASE_NAME); + $tableMap = $dbMap->getTable(ProReportingPeer::TABLE_NAME); + + if (! is_array($cols)) { + $cols = array($cols); + } + + foreach ($cols as $colName) { + if ($tableMap->containsColumn($colName)) { + $get = 'get' . $tableMap->getColumn($colName)->getPhpName(); + $columns[$colName] = $obj->$get(); + } + } + } else { + + } + + return BasePeer::doValidate(ProReportingPeer::DATABASE_NAME, ProReportingPeer::TABLE_NAME, $columns); + } + + /** + * Retrieve object using using composite pkey values. + * @param string $pro_uid + * @param int $month + * @param int $year + * @param Connection $con + * @return ProReporting + */ + public static function retrieveByPK($pro_uid, $month, $year, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $criteria = new Criteria(); + $criteria->add(ProReportingPeer::PRO_UID, $pro_uid); + $criteria->add(ProReportingPeer::MONTH, $month); + $criteria->add(ProReportingPeer::YEAR, $year); + $v = ProReportingPeer::doSelect($criteria, $con); + + return !empty($v) ? $v[0] : null; + } +} + + +// static code to register the map builder for this Peer with the main Propel class +if (Propel::isInit()) { + // the MapBuilder classes register themselves with Propel during initialization + // so we need to load them here. + try { + BaseProReportingPeer::getMapBuilder(); + } catch (Exception $e) { + Propel::log('Could not initialize Peer: ' . $e->getMessage(), Propel::LOG_ERR); + } +} else { + // even if Propel is not yet initialized, the map builder class can be registered + // now and then it will be loaded when Propel initializes. + require_once 'classes/model/map/ProReportingMapBuilder.php'; + Propel::registerMapBuilder('classes.model.map.ProReportingMapBuilder'); +} + diff --git a/workflow/engine/classes/model/om/BaseUsrReporting.php b/workflow/engine/classes/model/om/BaseUsrReporting.php new file mode 100644 index 000000000..9e2c73f50 --- /dev/null +++ b/workflow/engine/classes/model/om/BaseUsrReporting.php @@ -0,0 +1,1232 @@ +usr_uid; + } + + /** + * Get the [tas_uid] column value. + * + * @return string + */ + public function getTasUid() + { + + return $this->tas_uid; + } + + /** + * Get the [pro_uid] column value. + * + * @return string + */ + public function getProUid() + { + + return $this->pro_uid; + } + + /** + * Get the [month] column value. + * + * @return int + */ + public function getMonth() + { + + return $this->month; + } + + /** + * Get the [year] column value. + * + * @return int + */ + public function getYear() + { + + return $this->year; + } + + /** + * Get the [total_time_by_task] column value. + * + * @return double + */ + public function getTotalTimeByTask() + { + + return $this->total_time_by_task; + } + + /** + * Get the [total_cases_in] column value. + * + * @return double + */ + public function getTotalCasesIn() + { + + return $this->total_cases_in; + } + + /** + * Get the [total_cases_out] column value. + * + * @return double + */ + public function getTotalCasesOut() + { + + return $this->total_cases_out; + } + + /** + * Get the [user_hour_cost] column value. + * + * @return double + */ + public function getUserHourCost() + { + + return $this->user_hour_cost; + } + + /** + * Get the [avg_time] column value. + * + * @return double + */ + public function getAvgTime() + { + + return $this->avg_time; + } + + /** + * Get the [sdv_time] column value. + * + * @return double + */ + public function getSdvTime() + { + + return $this->sdv_time; + } + + /** + * Get the [configured_task_time] column value. + * + * @return double + */ + public function getConfiguredTaskTime() + { + + return $this->configured_task_time; + } + + /** + * Get the [total_cases_overdue] column value. + * + * @return double + */ + public function getTotalCasesOverdue() + { + + return $this->total_cases_overdue; + } + + /** + * Get the [total_cases_on_time] column value. + * + * @return double + */ + public function getTotalCasesOnTime() + { + + return $this->total_cases_on_time; + } + + /** + * Set the value of [usr_uid] column. + * + * @param string $v new value + * @return void + */ + public function setUsrUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->usr_uid !== $v) { + $this->usr_uid = $v; + $this->modifiedColumns[] = UsrReportingPeer::USR_UID; + } + + } // setUsrUid() + + /** + * Set the value of [tas_uid] column. + * + * @param string $v new value + * @return void + */ + public function setTasUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->tas_uid !== $v) { + $this->tas_uid = $v; + $this->modifiedColumns[] = UsrReportingPeer::TAS_UID; + } + + } // setTasUid() + + /** + * Set the value of [pro_uid] column. + * + * @param string $v new value + * @return void + */ + public function setProUid($v) + { + + // Since the native PHP type for this column is string, + // we will cast the input to a string (if it is not). + if ($v !== null && !is_string($v)) { + $v = (string) $v; + } + + if ($this->pro_uid !== $v) { + $this->pro_uid = $v; + $this->modifiedColumns[] = UsrReportingPeer::PRO_UID; + } + + } // setProUid() + + /** + * Set the value of [month] column. + * + * @param int $v new value + * @return void + */ + public function setMonth($v) + { + + // Since the native PHP type for this column is integer, + // we will cast the input value to an int (if it is not). + if ($v !== null && !is_int($v) && is_numeric($v)) { + $v = (int) $v; + } + + if ($this->month !== $v || $v === 0) { + $this->month = $v; + $this->modifiedColumns[] = UsrReportingPeer::MONTH; + } + + } // setMonth() + + /** + * Set the value of [year] column. + * + * @param int $v new value + * @return void + */ + public function setYear($v) + { + + // Since the native PHP type for this column is integer, + // we will cast the input value to an int (if it is not). + if ($v !== null && !is_int($v) && is_numeric($v)) { + $v = (int) $v; + } + + if ($this->year !== $v || $v === 0) { + $this->year = $v; + $this->modifiedColumns[] = UsrReportingPeer::YEAR; + } + + } // setYear() + + /** + * Set the value of [total_time_by_task] column. + * + * @param double $v new value + * @return void + */ + public function setTotalTimeByTask($v) + { + + if ($this->total_time_by_task !== $v) { + $this->total_time_by_task = $v; + $this->modifiedColumns[] = UsrReportingPeer::TOTAL_TIME_BY_TASK; + } + + } // setTotalTimeByTask() + + /** + * Set the value of [total_cases_in] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesIn($v) + { + + if ($this->total_cases_in !== $v) { + $this->total_cases_in = $v; + $this->modifiedColumns[] = UsrReportingPeer::TOTAL_CASES_IN; + } + + } // setTotalCasesIn() + + /** + * Set the value of [total_cases_out] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesOut($v) + { + + if ($this->total_cases_out !== $v) { + $this->total_cases_out = $v; + $this->modifiedColumns[] = UsrReportingPeer::TOTAL_CASES_OUT; + } + + } // setTotalCasesOut() + + /** + * Set the value of [user_hour_cost] column. + * + * @param double $v new value + * @return void + */ + public function setUserHourCost($v) + { + + if ($this->user_hour_cost !== $v) { + $this->user_hour_cost = $v; + $this->modifiedColumns[] = UsrReportingPeer::USER_HOUR_COST; + } + + } // setUserHourCost() + + /** + * Set the value of [avg_time] column. + * + * @param double $v new value + * @return void + */ + public function setAvgTime($v) + { + + if ($this->avg_time !== $v) { + $this->avg_time = $v; + $this->modifiedColumns[] = UsrReportingPeer::AVG_TIME; + } + + } // setAvgTime() + + /** + * Set the value of [sdv_time] column. + * + * @param double $v new value + * @return void + */ + public function setSdvTime($v) + { + + if ($this->sdv_time !== $v) { + $this->sdv_time = $v; + $this->modifiedColumns[] = UsrReportingPeer::SDV_TIME; + } + + } // setSdvTime() + + /** + * Set the value of [configured_task_time] column. + * + * @param double $v new value + * @return void + */ + public function setConfiguredTaskTime($v) + { + + if ($this->configured_task_time !== $v) { + $this->configured_task_time = $v; + $this->modifiedColumns[] = UsrReportingPeer::CONFIGURED_TASK_TIME; + } + + } // setConfiguredTaskTime() + + /** + * Set the value of [total_cases_overdue] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesOverdue($v) + { + + if ($this->total_cases_overdue !== $v) { + $this->total_cases_overdue = $v; + $this->modifiedColumns[] = UsrReportingPeer::TOTAL_CASES_OVERDUE; + } + + } // setTotalCasesOverdue() + + /** + * Set the value of [total_cases_on_time] column. + * + * @param double $v new value + * @return void + */ + public function setTotalCasesOnTime($v) + { + + if ($this->total_cases_on_time !== $v) { + $this->total_cases_on_time = $v; + $this->modifiedColumns[] = UsrReportingPeer::TOTAL_CASES_ON_TIME; + } + + } // setTotalCasesOnTime() + + /** + * Hydrates (populates) the object variables with values from the database resultset. + * + * An offset (1-based "start column") is specified so that objects can be hydrated + * with a subset of the columns in the resultset rows. This is needed, for example, + * for results of JOIN queries where the resultset row includes columns from two or + * more tables. + * + * @param ResultSet $rs The ResultSet class with cursor advanced to desired record pos. + * @param int $startcol 1-based offset column which indicates which restultset column to start with. + * @return int next starting column + * @throws PropelException - Any caught Exception will be rewrapped as a PropelException. + */ + public function hydrate(ResultSet $rs, $startcol = 1) + { + try { + + $this->usr_uid = $rs->getString($startcol + 0); + + $this->tas_uid = $rs->getString($startcol + 1); + + $this->pro_uid = $rs->getString($startcol + 2); + + $this->month = $rs->getInt($startcol + 3); + + $this->year = $rs->getInt($startcol + 4); + + $this->total_time_by_task = $rs->getFloat($startcol + 5); + + $this->total_cases_in = $rs->getFloat($startcol + 6); + + $this->total_cases_out = $rs->getFloat($startcol + 7); + + $this->user_hour_cost = $rs->getFloat($startcol + 8); + + $this->avg_time = $rs->getFloat($startcol + 9); + + $this->sdv_time = $rs->getFloat($startcol + 10); + + $this->configured_task_time = $rs->getFloat($startcol + 11); + + $this->total_cases_overdue = $rs->getFloat($startcol + 12); + + $this->total_cases_on_time = $rs->getFloat($startcol + 13); + + $this->resetModified(); + + $this->setNew(false); + + // FIXME - using NUM_COLUMNS may be clearer. + return $startcol + 14; // 14 = UsrReportingPeer::NUM_COLUMNS - UsrReportingPeer::NUM_LAZY_LOAD_COLUMNS). + + } catch (Exception $e) { + throw new PropelException("Error populating UsrReporting object", $e); + } + } + + /** + * Removes this object from datastore and sets delete attribute. + * + * @param Connection $con + * @return void + * @throws PropelException + * @see BaseObject::setDeleted() + * @see BaseObject::isDeleted() + */ + public function delete($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("This object has already been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(UsrReportingPeer::DATABASE_NAME); + } + + try { + $con->begin(); + UsrReportingPeer::doDelete($this, $con); + $this->setDeleted(true); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. If the object is new, + * it inserts it; otherwise an update is performed. This method + * wraps the doSave() worker method in a transaction. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update + * @throws PropelException + * @see doSave() + */ + public function save($con = null) + { + if ($this->isDeleted()) { + throw new PropelException("You cannot save an object that has been deleted."); + } + + if ($con === null) { + $con = Propel::getConnection(UsrReportingPeer::DATABASE_NAME); + } + + try { + $con->begin(); + $affectedRows = $this->doSave($con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Stores the object in the database. + * + * If the object is new, it inserts it; otherwise an update is performed. + * All related objects are also updated in this method. + * + * @param Connection $con + * @return int The number of rows affected by this insert/update and any referring + * @throws PropelException + * @see save() + */ + protected function doSave($con) + { + $affectedRows = 0; // initialize var to track total num of affected rows + if (!$this->alreadyInSave) { + $this->alreadyInSave = true; + + + // If this object has been modified, then save it to the database. + if ($this->isModified()) { + if ($this->isNew()) { + $pk = UsrReportingPeer::doInsert($this, $con); + $affectedRows += 1; // we are assuming that there is only 1 row per doInsert() which + // should always be true here (even though technically + // BasePeer::doInsert() can insert multiple rows). + + $this->setNew(false); + } else { + $affectedRows += UsrReportingPeer::doUpdate($this, $con); + } + $this->resetModified(); // [HL] After being saved an object is no longer 'modified' + } + + $this->alreadyInSave = false; + } + return $affectedRows; + } // doSave() + + /** + * Array of ValidationFailed objects. + * @var array ValidationFailed[] + */ + protected $validationFailures = array(); + + /** + * Gets any ValidationFailed objects that resulted from last call to validate(). + * + * + * @return array ValidationFailed[] + * @see validate() + */ + public function getValidationFailures() + { + return $this->validationFailures; + } + + /** + * Validates the objects modified field values and all objects related to this table. + * + * If $columns is either a column name or an array of column names + * only those columns are validated. + * + * @param mixed $columns Column name or an array of column names. + * @return boolean Whether all columns pass validation. + * @see doValidate() + * @see getValidationFailures() + */ + public function validate($columns = null) + { + $res = $this->doValidate($columns); + if ($res === true) { + $this->validationFailures = array(); + return true; + } else { + $this->validationFailures = $res; + return false; + } + } + + /** + * This function performs the validation work for complex object models. + * + * In addition to checking the current object, all related objects will + * also be validated. If all pass then true is returned; otherwise + * an aggreagated array of ValidationFailed objects will be returned. + * + * @param array $columns Array of column names to validate. + * @return mixed true if all validations pass; + array of ValidationFailed objects otherwise. + */ + protected function doValidate($columns = null) + { + if (!$this->alreadyInValidation) { + $this->alreadyInValidation = true; + $retval = null; + + $failureMap = array(); + + + if (($retval = UsrReportingPeer::doValidate($this, $columns)) !== true) { + $failureMap = array_merge($failureMap, $retval); + } + + + + $this->alreadyInValidation = false; + } + + return (!empty($failureMap) ? $failureMap : true); + } + + /** + * Retrieves a field from the object by name passed in as a string. + * + * @param string $name name + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return mixed Value of field. + */ + public function getByName($name, $type = BasePeer::TYPE_PHPNAME) + { + $pos = UsrReportingPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->getByPosition($pos); + } + + /** + * Retrieves a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @return mixed Value of field at $pos + */ + public function getByPosition($pos) + { + switch($pos) { + case 0: + return $this->getUsrUid(); + break; + case 1: + return $this->getTasUid(); + break; + case 2: + return $this->getProUid(); + break; + case 3: + return $this->getMonth(); + break; + case 4: + return $this->getYear(); + break; + case 5: + return $this->getTotalTimeByTask(); + break; + case 6: + return $this->getTotalCasesIn(); + break; + case 7: + return $this->getTotalCasesOut(); + break; + case 8: + return $this->getUserHourCost(); + break; + case 9: + return $this->getAvgTime(); + break; + case 10: + return $this->getSdvTime(); + break; + case 11: + return $this->getConfiguredTaskTime(); + break; + case 12: + return $this->getTotalCasesOverdue(); + break; + case 13: + return $this->getTotalCasesOnTime(); + break; + default: + return null; + break; + } // switch() + } + + /** + * Exports the object as an array. + * + * You can specify the key type of the array by passing one of the class + * type constants. + * + * @param string $keyType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return an associative array containing the field names (as keys) and field values + */ + public function toArray($keyType = BasePeer::TYPE_PHPNAME) + { + $keys = UsrReportingPeer::getFieldNames($keyType); + $result = array( + $keys[0] => $this->getUsrUid(), + $keys[1] => $this->getTasUid(), + $keys[2] => $this->getProUid(), + $keys[3] => $this->getMonth(), + $keys[4] => $this->getYear(), + $keys[5] => $this->getTotalTimeByTask(), + $keys[6] => $this->getTotalCasesIn(), + $keys[7] => $this->getTotalCasesOut(), + $keys[8] => $this->getUserHourCost(), + $keys[9] => $this->getAvgTime(), + $keys[10] => $this->getSdvTime(), + $keys[11] => $this->getConfiguredTaskTime(), + $keys[12] => $this->getTotalCasesOverdue(), + $keys[13] => $this->getTotalCasesOnTime(), + ); + return $result; + } + + /** + * Sets a field from the object by name passed in as a string. + * + * @param string $name peer name + * @param mixed $value field value + * @param string $type The type of fieldname the $name is of: + * one of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return void + */ + public function setByName($name, $value, $type = BasePeer::TYPE_PHPNAME) + { + $pos = UsrReportingPeer::translateFieldName($name, $type, BasePeer::TYPE_NUM); + return $this->setByPosition($pos, $value); + } + + /** + * Sets a field from the object by Position as specified in the xml schema. + * Zero-based. + * + * @param int $pos position in xml schema + * @param mixed $value field value + * @return void + */ + public function setByPosition($pos, $value) + { + switch($pos) { + case 0: + $this->setUsrUid($value); + break; + case 1: + $this->setTasUid($value); + break; + case 2: + $this->setProUid($value); + break; + case 3: + $this->setMonth($value); + break; + case 4: + $this->setYear($value); + break; + case 5: + $this->setTotalTimeByTask($value); + break; + case 6: + $this->setTotalCasesIn($value); + break; + case 7: + $this->setTotalCasesOut($value); + break; + case 8: + $this->setUserHourCost($value); + break; + case 9: + $this->setAvgTime($value); + break; + case 10: + $this->setSdvTime($value); + break; + case 11: + $this->setConfiguredTaskTime($value); + break; + case 12: + $this->setTotalCasesOverdue($value); + break; + case 13: + $this->setTotalCasesOnTime($value); + break; + } // switch() + } + + /** + * Populates the object using an array. + * + * This is particularly useful when populating an object from one of the + * request arrays (e.g. $_POST). This method goes through the column + * names, checking to see whether a matching key exists in populated + * array. If so the setByName() method is called for that column. + * + * You can specify the key type of the array by additionally passing one + * of the class type constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, + * TYPE_NUM. The default key type is the column's phpname (e.g. 'authorId') + * + * @param array $arr An array to populate the object from. + * @param string $keyType The type of keys the array uses. + * @return void + */ + public function fromArray($arr, $keyType = BasePeer::TYPE_PHPNAME) + { + $keys = UsrReportingPeer::getFieldNames($keyType); + + if (array_key_exists($keys[0], $arr)) { + $this->setUsrUid($arr[$keys[0]]); + } + + if (array_key_exists($keys[1], $arr)) { + $this->setTasUid($arr[$keys[1]]); + } + + if (array_key_exists($keys[2], $arr)) { + $this->setProUid($arr[$keys[2]]); + } + + if (array_key_exists($keys[3], $arr)) { + $this->setMonth($arr[$keys[3]]); + } + + if (array_key_exists($keys[4], $arr)) { + $this->setYear($arr[$keys[4]]); + } + + if (array_key_exists($keys[5], $arr)) { + $this->setTotalTimeByTask($arr[$keys[5]]); + } + + if (array_key_exists($keys[6], $arr)) { + $this->setTotalCasesIn($arr[$keys[6]]); + } + + if (array_key_exists($keys[7], $arr)) { + $this->setTotalCasesOut($arr[$keys[7]]); + } + + if (array_key_exists($keys[8], $arr)) { + $this->setUserHourCost($arr[$keys[8]]); + } + + if (array_key_exists($keys[9], $arr)) { + $this->setAvgTime($arr[$keys[9]]); + } + + if (array_key_exists($keys[10], $arr)) { + $this->setSdvTime($arr[$keys[10]]); + } + + if (array_key_exists($keys[11], $arr)) { + $this->setConfiguredTaskTime($arr[$keys[11]]); + } + + if (array_key_exists($keys[12], $arr)) { + $this->setTotalCasesOverdue($arr[$keys[12]]); + } + + if (array_key_exists($keys[13], $arr)) { + $this->setTotalCasesOnTime($arr[$keys[13]]); + } + + } + + /** + * Build a Criteria object containing the values of all modified columns in this object. + * + * @return Criteria The Criteria object containing all modified values. + */ + public function buildCriteria() + { + $criteria = new Criteria(UsrReportingPeer::DATABASE_NAME); + + if ($this->isColumnModified(UsrReportingPeer::USR_UID)) { + $criteria->add(UsrReportingPeer::USR_UID, $this->usr_uid); + } + + if ($this->isColumnModified(UsrReportingPeer::TAS_UID)) { + $criteria->add(UsrReportingPeer::TAS_UID, $this->tas_uid); + } + + if ($this->isColumnModified(UsrReportingPeer::PRO_UID)) { + $criteria->add(UsrReportingPeer::PRO_UID, $this->pro_uid); + } + + if ($this->isColumnModified(UsrReportingPeer::MONTH)) { + $criteria->add(UsrReportingPeer::MONTH, $this->month); + } + + if ($this->isColumnModified(UsrReportingPeer::YEAR)) { + $criteria->add(UsrReportingPeer::YEAR, $this->year); + } + + if ($this->isColumnModified(UsrReportingPeer::TOTAL_TIME_BY_TASK)) { + $criteria->add(UsrReportingPeer::TOTAL_TIME_BY_TASK, $this->total_time_by_task); + } + + if ($this->isColumnModified(UsrReportingPeer::TOTAL_CASES_IN)) { + $criteria->add(UsrReportingPeer::TOTAL_CASES_IN, $this->total_cases_in); + } + + if ($this->isColumnModified(UsrReportingPeer::TOTAL_CASES_OUT)) { + $criteria->add(UsrReportingPeer::TOTAL_CASES_OUT, $this->total_cases_out); + } + + if ($this->isColumnModified(UsrReportingPeer::USER_HOUR_COST)) { + $criteria->add(UsrReportingPeer::USER_HOUR_COST, $this->user_hour_cost); + } + + if ($this->isColumnModified(UsrReportingPeer::AVG_TIME)) { + $criteria->add(UsrReportingPeer::AVG_TIME, $this->avg_time); + } + + if ($this->isColumnModified(UsrReportingPeer::SDV_TIME)) { + $criteria->add(UsrReportingPeer::SDV_TIME, $this->sdv_time); + } + + if ($this->isColumnModified(UsrReportingPeer::CONFIGURED_TASK_TIME)) { + $criteria->add(UsrReportingPeer::CONFIGURED_TASK_TIME, $this->configured_task_time); + } + + if ($this->isColumnModified(UsrReportingPeer::TOTAL_CASES_OVERDUE)) { + $criteria->add(UsrReportingPeer::TOTAL_CASES_OVERDUE, $this->total_cases_overdue); + } + + if ($this->isColumnModified(UsrReportingPeer::TOTAL_CASES_ON_TIME)) { + $criteria->add(UsrReportingPeer::TOTAL_CASES_ON_TIME, $this->total_cases_on_time); + } + + + return $criteria; + } + + /** + * Builds a Criteria object containing the primary key for this object. + * + * Unlike buildCriteria() this method includes the primary key values regardless + * of whether or not they have been modified. + * + * @return Criteria The Criteria object containing value(s) for primary key(s). + */ + public function buildPkeyCriteria() + { + $criteria = new Criteria(UsrReportingPeer::DATABASE_NAME); + + $criteria->add(UsrReportingPeer::USR_UID, $this->usr_uid); + $criteria->add(UsrReportingPeer::TAS_UID, $this->tas_uid); + $criteria->add(UsrReportingPeer::MONTH, $this->month); + $criteria->add(UsrReportingPeer::YEAR, $this->year); + + return $criteria; + } + + /** + * Returns the composite primary key for this object. + * The array elements will be in same order as specified in XML. + * @return array + */ + public function getPrimaryKey() + { + $pks = array(); + + $pks[0] = $this->getUsrUid(); + + $pks[1] = $this->getTasUid(); + + $pks[2] = $this->getMonth(); + + $pks[3] = $this->getYear(); + + return $pks; + } + + /** + * Set the [composite] primary key. + * + * @param array $keys The elements of the composite key (order must match the order in XML file). + * @return void + */ + public function setPrimaryKey($keys) + { + + $this->setUsrUid($keys[0]); + + $this->setTasUid($keys[1]); + + $this->setMonth($keys[2]); + + $this->setYear($keys[3]); + + } + + /** + * Sets contents of passed object to values from current object. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param object $copyObj An object of UsrReporting (or compatible) type. + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @throws PropelException + */ + public function copyInto($copyObj, $deepCopy = false) + { + + $copyObj->setProUid($this->pro_uid); + + $copyObj->setTotalTimeByTask($this->total_time_by_task); + + $copyObj->setTotalCasesIn($this->total_cases_in); + + $copyObj->setTotalCasesOut($this->total_cases_out); + + $copyObj->setUserHourCost($this->user_hour_cost); + + $copyObj->setAvgTime($this->avg_time); + + $copyObj->setSdvTime($this->sdv_time); + + $copyObj->setConfiguredTaskTime($this->configured_task_time); + + $copyObj->setTotalCasesOverdue($this->total_cases_overdue); + + $copyObj->setTotalCasesOnTime($this->total_cases_on_time); + + + $copyObj->setNew(true); + + $copyObj->setUsrUid(NULL); // this is a pkey column, so set to default value + + $copyObj->setTasUid(NULL); // this is a pkey column, so set to default value + + $copyObj->setMonth('0'); // this is a pkey column, so set to default value + + $copyObj->setYear('0'); // this is a pkey column, so set to default value + + } + + /** + * Makes a copy of this object that will be inserted as a new row in table when saved. + * It creates a new object filling in the simple attributes, but skipping any primary + * keys that are defined for the table. + * + * If desired, this method can also make copies of all associated (fkey referrers) + * objects. + * + * @param boolean $deepCopy Whether to also copy all rows that refer (by fkey) to the current row. + * @return UsrReporting Clone of current object. + * @throws PropelException + */ + public function copy($deepCopy = false) + { + // we use get_class(), because this might be a subclass + $clazz = get_class($this); + $copyObj = new $clazz(); + $this->copyInto($copyObj, $deepCopy); + return $copyObj; + } + + /** + * Returns a peer instance associated with this om. + * + * Since Peer classes are not to have any instance attributes, this method returns the + * same instance for all member of this class. The method could therefore + * be static, but this would prevent one from overriding the behavior. + * + * @return UsrReportingPeer + */ + public function getPeer() + { + if (self::$peer === null) { + self::$peer = new UsrReportingPeer(); + } + return self::$peer; + } +} + diff --git a/workflow/engine/classes/model/om/BaseUsrReportingPeer.php b/workflow/engine/classes/model/om/BaseUsrReportingPeer.php new file mode 100644 index 000000000..5b878949f --- /dev/null +++ b/workflow/engine/classes/model/om/BaseUsrReportingPeer.php @@ -0,0 +1,636 @@ + array ('UsrUid', 'TasUid', 'ProUid', 'Month', 'Year', 'TotalTimeByTask', 'TotalCasesIn', 'TotalCasesOut', 'UserHourCost', 'AvgTime', 'SdvTime', 'ConfiguredTaskTime', 'TotalCasesOverdue', 'TotalCasesOnTime', ), + BasePeer::TYPE_COLNAME => array (UsrReportingPeer::USR_UID, UsrReportingPeer::TAS_UID, UsrReportingPeer::PRO_UID, UsrReportingPeer::MONTH, UsrReportingPeer::YEAR, UsrReportingPeer::TOTAL_TIME_BY_TASK, UsrReportingPeer::TOTAL_CASES_IN, UsrReportingPeer::TOTAL_CASES_OUT, UsrReportingPeer::USER_HOUR_COST, UsrReportingPeer::AVG_TIME, UsrReportingPeer::SDV_TIME, UsrReportingPeer::CONFIGURED_TASK_TIME, UsrReportingPeer::TOTAL_CASES_OVERDUE, UsrReportingPeer::TOTAL_CASES_ON_TIME, ), + BasePeer::TYPE_FIELDNAME => array ('USR_UID', 'TAS_UID', 'PRO_UID', 'MONTH', 'YEAR', 'TOTAL_TIME_BY_TASK', 'TOTAL_CASES_IN', 'TOTAL_CASES_OUT', 'USER_HOUR_COST', 'AVG_TIME', 'SDV_TIME', 'CONFIGURED_TASK_TIME', 'TOTAL_CASES_OVERDUE', 'TOTAL_CASES_ON_TIME', ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ) + ); + + /** + * holds an array of keys for quick access to the fieldnames array + * + * first dimension keys are the type constants + * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0 + */ + private static $fieldKeys = array ( + BasePeer::TYPE_PHPNAME => array ('UsrUid' => 0, 'TasUid' => 1, 'ProUid' => 2, 'Month' => 3, 'Year' => 4, 'TotalTimeByTask' => 5, 'TotalCasesIn' => 6, 'TotalCasesOut' => 7, 'UserHourCost' => 8, 'AvgTime' => 9, 'SdvTime' => 10, 'ConfiguredTaskTime' => 11, 'TotalCasesOverdue' => 12, 'TotalCasesOnTime' => 13, ), + BasePeer::TYPE_COLNAME => array (UsrReportingPeer::USR_UID => 0, UsrReportingPeer::TAS_UID => 1, UsrReportingPeer::PRO_UID => 2, UsrReportingPeer::MONTH => 3, UsrReportingPeer::YEAR => 4, UsrReportingPeer::TOTAL_TIME_BY_TASK => 5, UsrReportingPeer::TOTAL_CASES_IN => 6, UsrReportingPeer::TOTAL_CASES_OUT => 7, UsrReportingPeer::USER_HOUR_COST => 8, UsrReportingPeer::AVG_TIME => 9, UsrReportingPeer::SDV_TIME => 10, UsrReportingPeer::CONFIGURED_TASK_TIME => 11, UsrReportingPeer::TOTAL_CASES_OVERDUE => 12, UsrReportingPeer::TOTAL_CASES_ON_TIME => 13, ), + BasePeer::TYPE_FIELDNAME => array ('USR_UID' => 0, 'TAS_UID' => 1, 'PRO_UID' => 2, 'MONTH' => 3, 'YEAR' => 4, 'TOTAL_TIME_BY_TASK' => 5, 'TOTAL_CASES_IN' => 6, 'TOTAL_CASES_OUT' => 7, 'USER_HOUR_COST' => 8, 'AVG_TIME' => 9, 'SDV_TIME' => 10, 'CONFIGURED_TASK_TIME' => 11, 'TOTAL_CASES_OVERDUE' => 12, 'TOTAL_CASES_ON_TIME' => 13, ), + BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ) + ); + + /** + * @return MapBuilder the map builder for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getMapBuilder() + { + include_once 'classes/model/map/UsrReportingMapBuilder.php'; + return BasePeer::getMapBuilder('classes.model.map.UsrReportingMapBuilder'); + } + /** + * Gets a map (hash) of PHP names to DB column names. + * + * @return array The PHP to DB name map for this peer + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @deprecated Use the getFieldNames() and translateFieldName() methods instead of this. + */ + public static function getPhpNameMap() + { + if (self::$phpNameMap === null) { + $map = UsrReportingPeer::getTableMap(); + $columns = $map->getColumns(); + $nameMap = array(); + foreach ($columns as $column) { + $nameMap[$column->getPhpName()] = $column->getColumnName(); + } + self::$phpNameMap = $nameMap; + } + return self::$phpNameMap; + } + /** + * Translates a fieldname to another type + * + * @param string $name field name + * @param string $fromType One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @param string $toType One of the class type constants + * @return string translated name of the field. + */ + static public function translateFieldName($name, $fromType, $toType) + { + $toNames = self::getFieldNames($toType); + $key = isset(self::$fieldKeys[$fromType][$name]) ? self::$fieldKeys[$fromType][$name] : null; + if ($key === null) { + throw new PropelException("'$name' could not be found in the field names of type '$fromType'. These are: " . print_r(self::$fieldKeys[$fromType], true)); + } + return $toNames[$key]; + } + + /** + * Returns an array of of field names. + * + * @param string $type The type of fieldnames to return: + * One of the class type constants TYPE_PHPNAME, + * TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM + * @return array A list of field names + */ + + static public function getFieldNames($type = BasePeer::TYPE_PHPNAME) + { + if (!array_key_exists($type, self::$fieldNames)) { + throw new PropelException('Method getFieldNames() expects the parameter $type to be one of the class constants TYPE_PHPNAME, TYPE_COLNAME, TYPE_FIELDNAME, TYPE_NUM. ' . $type . ' was given.'); + } + return self::$fieldNames[$type]; + } + + /** + * Convenience method which changes table.column to alias.column. + * + * Using this method you can maintain SQL abstraction while using column aliases. + * + * $c->addAlias("alias1", TablePeer::TABLE_NAME); + * $c->addJoin(TablePeer::alias("alias1", TablePeer::PRIMARY_KEY_COLUMN), TablePeer::PRIMARY_KEY_COLUMN); + * + * @param string $alias The alias for the current table. + * @param string $column The column name for current table. (i.e. UsrReportingPeer::COLUMN_NAME). + * @return string + */ + public static function alias($alias, $column) + { + return str_replace(UsrReportingPeer::TABLE_NAME.'.', $alias.'.', $column); + } + + /** + * Add all the columns needed to create a new object. + * + * Note: any columns that were marked with lazyLoad="true" in the + * XML schema will not be added to the select list and only loaded + * on demand. + * + * @param criteria object containing the columns to add. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function addSelectColumns(Criteria $criteria) + { + + $criteria->addSelectColumn(UsrReportingPeer::USR_UID); + + $criteria->addSelectColumn(UsrReportingPeer::TAS_UID); + + $criteria->addSelectColumn(UsrReportingPeer::PRO_UID); + + $criteria->addSelectColumn(UsrReportingPeer::MONTH); + + $criteria->addSelectColumn(UsrReportingPeer::YEAR); + + $criteria->addSelectColumn(UsrReportingPeer::TOTAL_TIME_BY_TASK); + + $criteria->addSelectColumn(UsrReportingPeer::TOTAL_CASES_IN); + + $criteria->addSelectColumn(UsrReportingPeer::TOTAL_CASES_OUT); + + $criteria->addSelectColumn(UsrReportingPeer::USER_HOUR_COST); + + $criteria->addSelectColumn(UsrReportingPeer::AVG_TIME); + + $criteria->addSelectColumn(UsrReportingPeer::SDV_TIME); + + $criteria->addSelectColumn(UsrReportingPeer::CONFIGURED_TASK_TIME); + + $criteria->addSelectColumn(UsrReportingPeer::TOTAL_CASES_OVERDUE); + + $criteria->addSelectColumn(UsrReportingPeer::TOTAL_CASES_ON_TIME); + + } + + const COUNT = 'COUNT(USR_REPORTING.USR_UID)'; + const COUNT_DISTINCT = 'COUNT(DISTINCT USR_REPORTING.USR_UID)'; + + /** + * Returns the number of rows matching criteria. + * + * @param Criteria $criteria + * @param boolean $distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria). + * @param Connection $con + * @return int Number of matching rows. + */ + public static function doCount(Criteria $criteria, $distinct = false, $con = null) + { + // we're going to modify criteria, so copy it first + $criteria = clone $criteria; + + // clear out anything that might confuse the ORDER BY clause + $criteria->clearSelectColumns()->clearOrderByColumns(); + if ($distinct || in_array(Criteria::DISTINCT, $criteria->getSelectModifiers())) { + $criteria->addSelectColumn(UsrReportingPeer::COUNT_DISTINCT); + } else { + $criteria->addSelectColumn(UsrReportingPeer::COUNT); + } + + // just in case we're grouping: add those columns to the select statement + foreach ($criteria->getGroupByColumns() as $column) { + $criteria->addSelectColumn($column); + } + + $rs = UsrReportingPeer::doSelectRS($criteria, $con); + if ($rs->next()) { + return $rs->getInt(1); + } else { + // no rows returned; we infer that means 0 matches. + return 0; + } + } + /** + * Method to select one object from the DB. + * + * @param Criteria $criteria object used to create the SELECT statement. + * @param Connection $con + * @return UsrReporting + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelectOne(Criteria $criteria, $con = null) + { + $critcopy = clone $criteria; + $critcopy->setLimit(1); + $objects = UsrReportingPeer::doSelect($critcopy, $con); + if ($objects) { + return $objects[0]; + } + return null; + } + /** + * Method to do selects. + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con + * @return array Array of selected Objects + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doSelect(Criteria $criteria, $con = null) + { + return UsrReportingPeer::populateObjects(UsrReportingPeer::doSelectRS($criteria, $con)); + } + /** + * Prepares the Criteria object and uses the parent doSelect() + * method to get a ResultSet. + * + * Use this method directly if you want to just get the resultset + * (instead of an array of objects). + * + * @param Criteria $criteria The Criteria object used to build the SELECT statement. + * @param Connection $con the connection to use + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + * @return ResultSet The resultset object with numerically-indexed fields. + * @see BasePeer::doSelect() + */ + public static function doSelectRS(Criteria $criteria, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if (!$criteria->getSelectColumns()) { + $criteria = clone $criteria; + UsrReportingPeer::addSelectColumns($criteria); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + // BasePeer returns a Creole ResultSet, set to return + // rows indexed numerically. + return BasePeer::doSelect($criteria, $con); + } + /** + * The returned array will contain objects of the default type or + * objects that inherit from the default. + * + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function populateObjects(ResultSet $rs) + { + $results = array(); + + // set the class once to avoid overhead in the loop + $cls = UsrReportingPeer::getOMClass(); + $cls = Propel::import($cls); + // populate the object(s) + while ($rs->next()) { + + $obj = new $cls(); + $obj->hydrate($rs); + $results[] = $obj; + + } + return $results; + } + /** + * Returns the TableMap related to this peer. + * This method is not needed for general use but a specific application could have a need. + * @return TableMap + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function getTableMap() + { + return Propel::getDatabaseMap(self::DATABASE_NAME)->getTable(self::TABLE_NAME); + } + + /** + * The class that the Peer will make instances of. + * + * This uses a dot-path notation which is tranalted into a path + * relative to a location on the PHP include_path. + * (e.g. path.to.MyClass -> 'path/to/MyClass.php') + * + * @return string path.to.ClassName + */ + public static function getOMClass() + { + return UsrReportingPeer::CLASS_DEFAULT; + } + + /** + * Method perform an INSERT on the database, given a UsrReporting or Criteria object. + * + * @param mixed $values Criteria or UsrReporting object containing data that is used to create the INSERT statement. + * @param Connection $con the connection to use + * @return mixed The new primary key. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doInsert($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } else { + $criteria = $values->buildCriteria(); // build Criteria from UsrReporting object + } + + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + try { + // use transaction because $criteria could contain info + // for more than one table (I guess, conceivably) + $con->begin(); + $pk = BasePeer::doInsert($criteria, $con); + $con->commit(); + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + + return $pk; + } + + /** + * Method perform an UPDATE on the database, given a UsrReporting or Criteria object. + * + * @param mixed $values Criteria or UsrReporting object containing data create the UPDATE statement. + * @param Connection $con The connection to use (specify Connection exert more control over transactions). + * @return int The number of affected rows (if supported by underlying database driver). + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doUpdate($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + + $selectCriteria = new Criteria(self::DATABASE_NAME); + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + + $comparison = $criteria->getComparison(UsrReportingPeer::USR_UID); + $selectCriteria->add(UsrReportingPeer::USR_UID, $criteria->remove(UsrReportingPeer::USR_UID), $comparison); + + $comparison = $criteria->getComparison(UsrReportingPeer::TAS_UID); + $selectCriteria->add(UsrReportingPeer::TAS_UID, $criteria->remove(UsrReportingPeer::TAS_UID), $comparison); + + $comparison = $criteria->getComparison(UsrReportingPeer::MONTH); + $selectCriteria->add(UsrReportingPeer::MONTH, $criteria->remove(UsrReportingPeer::MONTH), $comparison); + + $comparison = $criteria->getComparison(UsrReportingPeer::YEAR); + $selectCriteria->add(UsrReportingPeer::YEAR, $criteria->remove(UsrReportingPeer::YEAR), $comparison); + + } else { + $criteria = $values->buildCriteria(); // gets full criteria + $selectCriteria = $values->buildPkeyCriteria(); // gets criteria w/ primary key(s) + } + + // set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + return BasePeer::doUpdate($selectCriteria, $criteria, $con); + } + + /** + * Method to DELETE all rows from the USR_REPORTING table. + * + * @return int The number of affected rows (if supported by underlying database driver). + */ + public static function doDeleteAll($con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $affectedRows = 0; // initialize var to track total num of affected rows + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + $affectedRows += BasePeer::doDeleteAll(UsrReportingPeer::TABLE_NAME, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Method perform a DELETE on the database, given a UsrReporting or Criteria object OR a primary key value. + * + * @param mixed $values Criteria or UsrReporting object or primary key or array of primary keys + * which is used to create the DELETE statement + * @param Connection $con the connection to use + * @return int The number of affected rows (if supported by underlying database driver). + * This includes CASCADE-related rows + * if supported by native driver or if emulated using Propel. + * @throws PropelException Any exceptions caught during processing will be + * rethrown wrapped into a PropelException. + */ + public static function doDelete($values, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(UsrReportingPeer::DATABASE_NAME); + } + + if ($values instanceof Criteria) { + $criteria = clone $values; // rename for clarity + } elseif ($values instanceof UsrReporting) { + + $criteria = $values->buildPkeyCriteria(); + } else { + // it must be the primary key + $criteria = new Criteria(self::DATABASE_NAME); + // primary key is composite; we therefore, expect + // the primary key passed to be an array of pkey + // values + if (count($values) == count($values, COUNT_RECURSIVE)) { + // array is not multi-dimensional + $values = array($values); + } + $vals = array(); + foreach ($values as $value) { + + $vals[0][] = $value[0]; + $vals[1][] = $value[1]; + $vals[2][] = $value[2]; + $vals[3][] = $value[3]; + } + + $criteria->add(UsrReportingPeer::USR_UID, $vals[0], Criteria::IN); + $criteria->add(UsrReportingPeer::TAS_UID, $vals[1], Criteria::IN); + $criteria->add(UsrReportingPeer::MONTH, $vals[2], Criteria::IN); + $criteria->add(UsrReportingPeer::YEAR, $vals[3], Criteria::IN); + } + + // Set the correct dbName + $criteria->setDbName(self::DATABASE_NAME); + + $affectedRows = 0; // initialize var to track total num of affected rows + + try { + // use transaction because $criteria could contain info + // for more than one table or we could emulating ON DELETE CASCADE, etc. + $con->begin(); + + $affectedRows += BasePeer::doDelete($criteria, $con); + $con->commit(); + return $affectedRows; + } catch (PropelException $e) { + $con->rollback(); + throw $e; + } + } + + /** + * Validates all modified columns of given UsrReporting object. + * If parameter $columns is either a single column name or an array of column names + * than only those columns are validated. + * + * NOTICE: This does not apply to primary or foreign keys for now. + * + * @param UsrReporting $obj The object to validate. + * @param mixed $cols Column name or array of column names. + * + * @return mixed TRUE if all columns are valid or the error message of the first invalid column. + */ + public static function doValidate(UsrReporting $obj, $cols = null) + { + $columns = array(); + + if ($cols) { + $dbMap = Propel::getDatabaseMap(UsrReportingPeer::DATABASE_NAME); + $tableMap = $dbMap->getTable(UsrReportingPeer::TABLE_NAME); + + if (! is_array($cols)) { + $cols = array($cols); + } + + foreach ($cols as $colName) { + if ($tableMap->containsColumn($colName)) { + $get = 'get' . $tableMap->getColumn($colName)->getPhpName(); + $columns[$colName] = $obj->$get(); + } + } + } else { + + } + + return BasePeer::doValidate(UsrReportingPeer::DATABASE_NAME, UsrReportingPeer::TABLE_NAME, $columns); + } + + /** + * Retrieve object using using composite pkey values. + * @param string $usr_uid + * @param string $tas_uid + * @param int $month + * @param int $year + * @param Connection $con + * @return UsrReporting + */ + public static function retrieveByPK($usr_uid, $tas_uid, $month, $year, $con = null) + { + if ($con === null) { + $con = Propel::getConnection(self::DATABASE_NAME); + } + $criteria = new Criteria(); + $criteria->add(UsrReportingPeer::USR_UID, $usr_uid); + $criteria->add(UsrReportingPeer::TAS_UID, $tas_uid); + $criteria->add(UsrReportingPeer::MONTH, $month); + $criteria->add(UsrReportingPeer::YEAR, $year); + $v = UsrReportingPeer::doSelect($criteria, $con); + + return !empty($v) ? $v[0] : null; + } +} + + +// static code to register the map builder for this Peer with the main Propel class +if (Propel::isInit()) { + // the MapBuilder classes register themselves with Propel during initialization + // so we need to load them here. + try { + BaseUsrReportingPeer::getMapBuilder(); + } catch (Exception $e) { + Propel::log('Could not initialize Peer: ' . $e->getMessage(), Propel::LOG_ERR); + } +} else { + // even if Propel is not yet initialized, the map builder class can be registered + // now and then it will be loaded when Propel initializes. + require_once 'classes/model/map/UsrReportingMapBuilder.php'; + Propel::registerMapBuilder('classes.model.map.UsrReportingMapBuilder'); +} + diff --git a/workflow/engine/controllers/strategicDashboard.php b/workflow/engine/controllers/strategicDashboard.php new file mode 100644 index 000000000..3ca5eaaf9 --- /dev/null +++ b/workflow/engine/controllers/strategicDashboard.php @@ -0,0 +1,211 @@ +userCanAccess('PM_DASHBOARD') != 1) { + G::SendTemporalMessage('ID_USER_HAVENT_RIGHTS_PAGE', 'error', 'labels'); + G::header( 'location: login/login' ); + exit(0); + } + $this->usrId = $RBAC->aUserInfo['USER_INFO']['USR_UID']; + $this->urlProxy = '/api/1.0/' . SYS_SYS . '/'; + //change + $clientId = 'x-pm-local-client'; + $client = $this->getClientCredentials($clientId); + $authCode = $this->getAuthorizationCode($client); + $debug = false; //System::isDebugMode(); + + $loader = Maveriks\Util\ClassLoader::getInstance(); + $loader->add(PATH_TRUNK . 'vendor/bshaffer/oauth2-server-php/src/', "OAuth2"); + + $request = array( + 'grant_type' => 'authorization_code', + 'code' => $authCode + ); + $server = array( + 'REQUEST_METHOD' => 'POST' + ); + $headers = array( + "PHP_AUTH_USER" => $client['CLIENT_ID'], + "PHP_AUTH_PW" => $client['CLIENT_SECRET'], + "Content-Type" => "multipart/form-data;", + "Authorization" => "Basic " . base64_encode($client['CLIENT_ID'] . ":" . $client['CLIENT_SECRET']) + ); + + $request = new \OAuth2\Request(array(), $request, array(), array(), array(), $server, null, $headers); + $oauthServer = new \ProcessMaker\Services\OAuth2\Server(); + $response = $oauthServer->postToken($request, true); + $this->clientToken = $response->getParameters(); + $this->clientToken["client_id"] = $client['CLIENT_ID']; + $this->clientToken["client_secret"] = $client['CLIENT_SECRET']; + } + + private function getClientCredentials($clientId) + { + $oauthQuery = new ProcessMaker\Services\OAuth2\PmPdo($this->getDsn()); + return $oauthQuery->getClientDetails($clientId); + } + + private function getAuthorizationCode($client) + { + \ProcessMaker\Services\OAuth2\Server::setDatabaseSource($this->getDsn()); + \ProcessMaker\Services\OAuth2\Server::setPmClientId($client['CLIENT_ID']); + + $oauthServer = new \ProcessMaker\Services\OAuth2\Server(); + $userId = $_SESSION['USER_LOGGED']; + $authorize = true; + $_GET = array_merge($_GET, array( + 'response_type' => 'code', + 'client_id' => $client['CLIENT_ID'], + 'scope' => implode(' ', $oauthServer->getScope()) + )); + + $response = $oauthServer->postAuthorize($authorize, $userId, true); + $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40); + + return $code; + } + + private function getDsn() + { + list($host, $port) = strpos(DB_HOST, ':') !== false ? explode(':', DB_HOST) : array(DB_HOST, ''); + $port = empty($port) ? '' : ";port=$port"; + $dsn = DB_ADAPTER.':host='.$host.';dbname='.DB_NAME.$port; + + return array('dsn' => $dsn, 'username' => DB_USER, 'password' => DB_PASS); + } + + // Functions for the StrategicDashboards + + public function dashboardList () + { + try { + $this->includeExtJS( 'strategicDashboard/dashboardList' ); + if (isset( $_SESSION['__StrategicDashboard_ERROR__'] )) { + $this->setJSVar( '__StrategicDashboard_ERROR__', $_SESSION['__StrategicDashboard_ERROR__'] ); + unset( $_SESSION['__StrategicDashboard_ERROR__'] ); + } + $this->setView( 'strategicDashboard/dashboardList' ); + + $this->setJSVar('urlProxy',$this->urlProxy); + $this->setJSVar('credentials',$this->clientToken); + G::RenderPage( 'publish', 'extJs' ); + } catch (Exception $error) { + $_SESSION['__DASHBOARD_ERROR__'] = $error->getMessage(); + die(); + } + } + + public function formDashboard ($data) + { + try { + + $this->includeExtJS( 'strategicDashboard/formDashboard', true, true ); + $this->setView( 'strategicDashboard/formDashboard' ); + + $this->setJSVar('DAS_UID', ''); + $this->setJSVar('urlProxy',$this->urlProxy); + $this->setJSVar('credentials',$this->clientToken); + + G::RenderPage( 'publish', 'extJs' ); + return null; + } catch (Exception $error) { + $_SESSION['__DASHBOARD_ERROR__'] = $error->getMessage(); + G::header( 'Location: dashboardList' ); + die(); + } + } + + public function formEditDashboard ($data) + { + try { + + $this->includeExtJS( 'strategicDashboard/formDashboard', true, true ); + $this->setView( 'strategicDashboard/formDashboard' ); + + $dasUid = isset($_REQUEST['DAS_UID']) ? $_REQUEST['DAS_UID'] : ''; + $this->setJSVar('DAS_UID', $dasUid); + $this->setJSVar('urlProxy',$this->urlProxy); + $this->setJSVar('credentials',$this->clientToken); + + G::RenderPage( 'publish', 'extJs' ); + return null; + } catch (Exception $error) { + $_SESSION['__DASHBOARD_ERROR__'] = $error->getMessage(); + G::header( 'Location: dashboardList' ); + die(); + } + } + + public function viewDashboard () + { + try { + if (isset( $_SESSION['__StrategicDashboard_ERROR__'] )) { + $this->setJSVar( '__StrategicDashboard_ERROR__', $_SESSION['__StrategicDashboard_ERROR__'] ); + unset( $_SESSION['__StrategicDashboard_ERROR__'] ); + } + $this->setView( 'strategicDashboard/viewDashboard' ); + + $this->setVar('urlProxy',$this->urlProxy); + $this->setVar('usrId',$this->usrId); + $this->setVar('credentials',$this->clientToken); + + $translation = array(); + + $translation['ID_MANAGERS_DASHBOARDS'] = G::LoadTranslation( 'ID_MANAGERS_DASHBOARDS'); + $translation['ID_PRO_EFFICIENCY_INDEX'] = G::LoadTranslation( 'ID_PRO_EFFICIENCY_INDEX'); + $translation['ID_EFFICIENCY_USER'] = G::LoadTranslation( 'ID_EFFICIENCY_USER'); + $translation['ID_COMPLETED_CASES'] = G::LoadTranslation( 'ID_COMPLETED_CASES'); + $translation['ID_WELL_DONE'] = G::LoadTranslation( 'ID_WELL_DONE'); + $translation['ID_NUMBER_CASES'] = G::LoadTranslation( 'ID_NUMBER_CASES'); + $translation['ID_EFFICIENCY_INDEX'] = G::LoadTranslation( 'ID_EFFICIENCY_INDEX'); + $translation['ID_INEFFICIENCY_COST'] = G::LoadTranslation( 'ID_INEFFICIENCY_COST'); + $translation['ID_EFFICIENCY_COST'] = G::LoadTranslation( 'ID_EFFICIENCY_COST'); + $translation['ID_RELATED_PROCESS'] = G::LoadTranslation( 'ID_RELATED_PROCESS'); + $translation['ID_RELATED_GROUPS'] = G::LoadTranslation( 'ID_RELATED_GROUPS'); + $translation['ID_RELATED_TASKS'] = G::LoadTranslation( 'ID_RELATED_TASKS'); + $translation['ID_RELATED_USERS'] = G::LoadTranslation( 'ID_RELATED_USERS'); + $translation['ID_GRID_PAGE_NO_DASHBOARD_MESSAGE'] = G::LoadTranslation( 'ID_GRID_PAGE_NO_DASHBOARD_MESSAGE'); + $translation['ID_PROCESS_TASKS'] = G::LoadTranslation( 'ID_PROCESS_TASKS'); + $translation['ID_TIME_HOURS'] = G::LoadTranslation( 'ID_TIME_HOURS'); + $translation['ID_GROUPS'] = G::LoadTranslation( 'ID_GROUPS'); + $translation['ID_YEAR'] = G::LoadTranslation( 'ID_YEAR'); + $translation['ID_USERS'] = G::LoadTranslation( 'ID_USERS'); + + $this->setVar('translation', $translation); + $this->render(); + } catch (Exception $error) { + $_SESSION['__DASHBOARD_ERROR__'] = $error->getMessage(); + die(); + } + } + + public function viewDashboardIE () + { + try { + $this->setView( 'strategicDashboard/viewDashboardIE' ); + $this->render(); + } catch (Exception $error) { + $_SESSION['__DASHBOARD_ERROR__'] = $error->getMessage(); + die(); + } + } +} diff --git a/workflow/engine/js/strategicDashboard/bootstrap.min.js b/workflow/engine/js/strategicDashboard/bootstrap.min.js new file mode 100644 index 000000000..b04a0e82f --- /dev/null +++ b/workflow/engine/js/strategicDashboard/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});return this.$element.trigger(j),j.isDefaultPrevented()?void 0:(this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this)};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);!e&&f.toggle&&"show"==c&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(b){a(d).remove(),a(e).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(b.RESET).addClass("affix");var a=this.$window.scrollTop(),c=this.$element.offset();return this.pinnedOffset=c.top-a},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"top"==this.affixed&&(e.top+=d),"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(b.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:c-h-this.$element.height()}))}}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file diff --git a/workflow/engine/js/strategicDashboard/dashboard.js b/workflow/engine/js/strategicDashboard/dashboard.js new file mode 100644 index 000000000..3f92dde1c --- /dev/null +++ b/workflow/engine/js/strategicDashboard/dashboard.js @@ -0,0 +1,1181 @@ + var peiParams = { + canvas : { + containerId:'proEfficGenGraph', + width:300, + height:300, + stretch:true + }, + graph: { + allowDrillDown:false, + allowTransition:true, + showTip: true, + allowZoom: true, //verificar navegadores... + gapWidth:0.2, + useShadows: true, //for Firefox and Chrome + thickness: 30, + showLabels: true, + colorPalette: ['#5486bf','#bf8d54','#acb30c','#7a0c0c','#bc0000','#906090','#007efb','#62284a','#0c7a7a'] + } + }; + + var ueiParams = { + canvas : { + containerId:'proEfficGenGraph', + width:300, + height:300, + stretch:true + }, + graph: { + allowTransition: false, + allowDrillDown: true, + showTip: true, + allowZoom: false, + useShadows: false, + gridLinesX: true, + gridLinesY: true, + area: {visible: false, css:"area"}, + axisX:{ showAxis: true, label: G_STRING.ID_GROUPS }, + axisY:{ showAxis: true, label: G_STRING.ID_TIME_HOURS }, + showErrorBars: true + } + }; + + + var generalLineParams1 = { + canvas : { + containerId:'generalGraph1', + width:300, + height:300, + stretch:true + }, + graph: { + allowTransition: false, + allowDrillDown: true, + showTip: true, + allowZoom: false, + useShadows: false, + gridLinesX: true, + gridLinesY: true, + area: {visible: false, css:"area"}, + axisX:{ showAxis: true, label: G_STRING.ID_PROCESS_TASKS }, + axisY:{ showAxis: true, label: G_STRING.ID_TIME_HOURS }, + showErrorBars: false + } + }; + + var generalLineParams2 = { + canvas : { + containerId:'generalGraph2', + width:300, + height:300, + stretch:true + }, + graph: { + allowTransition: false, + allowDrillDown: true, + showTip: true, + allowZoom: false, + useShadows: false, + gridLinesX: true, + gridLinesY: true, + area: {visible: false, css:"area"}, + axisX:{ showAxis: true, label: G_STRING.ID_PROCESS_TASKS }, + axisY:{ showAxis: true, label: G_STRING.ID_TIME_HOURS }, + showErrorBars: false + } + }; + + + + var generalBarParams1 = { + canvas : { + containerId:'generalGraph1', + width:300, + height:300, + stretch:true + }, + graph: { + allowDrillDown:false, + allowTransition:true, + axisX:{ showAxis: true, label: G_STRING.ID_YEAR }, + axisY:{ showAxis: true, label: "Q" }, + gridLinesX:false, + gridLinesY:true, + showTip: true, + allowZoom: true, + useShadows: true, + paddingTop: 50, + colorPalette: ['#5486bf','#bf8d54','#acb30c','#7a0c0c','#bc0000','#906090','#007efb','#62284a','#0c7a7a','#74a9a9'] + } + }; + + var generalBarParams2 = { + canvas : { + containerId:'generalGraph2', + width:300, + height:300, + stretch:true + }, + graph: { + allowDrillDown:false, + allowTransition:true, + axisX:{ showAxis: true, label: G_STRING.ID_YEAR }, + axisY:{ showAxis: true, label: "Q" }, + gridLinesX:false, + gridLinesY:true, + showTip: true, + allowZoom: true, + useShadows: true, + paddingTop: 50, + colorPalette: ['#5486bf','#bf8d54','#acb30c','#7a0c0c','#bc0000','#906090','#007efb','#62284a','#0c7a7a','#74a9a9'] + } + }; + var peiDetailParams = { + canvas : { + containerId:'proEfficGraph', + width:300, + height:300, + stretch:true + }, + graph: { + allowTransition: false, + allowDrillDown: true, + showTip: true, + allowZoom: false, + useShadows: false, + gridLinesX: true, + gridLinesY: true, + area: {visible: false, css:"area"}, + axisX:{ showAxis: true, label: G_STRING.ID_PROCESS_TASKS }, + axisY:{ showAxis: true, label: G_STRING.ID_TIME_HOURS }, + showErrorBars: true + + } + }; + + var ueiDetailParams = { + canvas : { + containerId:'proEfficGraph', + width:300, + height:300, + stretch:true + }, + graph: { + allowTransition: false, + allowDrillDown: true, + showTip: true, + allowZoom: false, + useShadows: false, + gridLinesX: true, + gridLinesY: true, + area: {visible: false, css:"area"}, + axisX:{ showAxis: true, label: G_STRING.ID_USERS }, + axisY:{ showAxis: true, label: G_STRING.ID_TIME_HOURS }, + showErrorBars: true + + } + }; + + //Adding data to + function animateprogress (id, index, comparative, name, indUid, direction){ + var getRequestAnimationFrame = function () { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function ( callback ){ + window.setTimeout(enroute, 1 / 60 * 1000); + }; + }; + + var fpAnimationFrame = getRequestAnimationFrame(); + var i = 0; + var j = 0; + + if(name.length>20){ + name = name.substring( -20, 20 ); + name = name+"..."; + } + + index = validaNull(index); + + document.getElementById(id+"Huge"+indUid).innerHTML = index; + document.getElementById(id+"Small"+indUid).innerHTML = comparative; + document.getElementById(id+"Span"+indUid).innerHTML = name; + + if(id == "proEffic" || id == "userEffic"){ + if(comparative<0){ + if(id == "proEffic"){ + $(document.getElementsByClassName("proGreen")).removeClass("panel-green").addClass("panel-red"); + $(document.getElementsByClassName("up")).removeClass("fa-chevron-up").addClass("fa-chevron-down"); + } + } else if(comparative>=0){ + $(document.getElementsByClassName("proRed")).removeClass("panel-red").addClass("panel-green"); + if(comparative==0){ + $(document.getElementsByClassName("down")).removeClass("fa-chevron-down").addClass("fa-circle-o"); + $(document.getElementsByClassName("up")).removeClass("fa-chevron-up").addClass("fa-circle-o"); + } else { + $(document.getElementsByClassName("down")).removeClass("fa-chevron-down").addClass("fa-chevron-up"); + } + } + } + + if(id == "generalGreat" || id == "generalLow"){ + var animacion = function () { + var comp = parseInt(comparative); + $(document.getElementById(id+indUid)).attr('aria-valuemax', comp); + var indexToPaint = index*100/comp; + if (i<=indexToPaint) + { + $(document.getElementById(id+indUid)).css('width', i+'%').attr('aria-valuenow', i); + i++; + fpAnimationFrame(animacion); + } + + if(j<=index){ + document.getElementById(id+"Huge"+indUid).innerHTML = j+"%"; + j++; + fpAnimationFrame(animacion); + } + + var direc = (direction == "1")? "<" : ">"; + if(id == "generalLow"){ + document.getElementById(id+"Small"+indUid).innerHTML = "Goal "+direc+" "+comparative+"%"; + } else{//si esq es positivo mostramos Well Done y la clase q setea las letras en blanco + document.getElementById(id+"Small"+indUid).innerHTML = "("+direc+" "+comparative+" %) "+ G_STRING.ID_WELL_DONE; + } + } + fpAnimationFrame(animacion); + } + }; + + //Button by dashbutton + var dasButton = '
'; + + //Items by each type: + var proEffic = '
'; + + var userEffic = ''; + + var compCases = ''; + + var numCases = ''; + + //Data by Indicator elements: + var proEfficDataGen = '
'+ G_STRING.ID_PRO_EFFICIENCY_INDEX +'
26%
'+ G_STRING.ID_EFFICIENCY_INDEX +'
$1813.50
'+ G_STRING.ID_INEFFICIENCY_COST +'
'; + + var proEfficData = '
26%
'+ G_STRING.ID_EFFICIENCY_INDEX +'
$1813.50
'+ G_STRING.ID_INEFFICIENCY_COST +'
'; + + var proEfficDetail = ''; + + var proEfficTaskDetail = '
\ +
\ +
Task 1
\ +
\ +
\ +
\ +
\ +
\ +
0.95
\ +
'+ G_STRING.ID_EFFICIENCY_COST +'
\ +
\ +
\ +
4.3
\ +
Average Time
\ +
\ +
\ +
1.3
\ +
Deviation
\ +
\ +
\ +
\ +
\ +
'; + + var userTaskDetail = '
\ +
\ +
Task 1
\ +
\ +
\ +
\ +
\ +
\ +
0.95
\ +
'+ G_STRING.ID_EFFICIENCY_INDEX +'
\ +
\ +
\ +
\ +
1.3
\ +
'+ G_STRING.ID_INEFFICIENCY_COST +'
\ +
\ +
\ +
\ +
\ +
'; + + var generalDataLow = '
'; + + var generalDataGreat = '
'; + + + var oType; + var actualDashId; + + //fecha actual + var date = new Date(); + var dateMonth = date.getMonth(); + var dateYear = date.getFullYear(); + + var dateActual = "01-"+(dateMonth+1)+"-"+dateYear; + var dateActualEnd = "30-"+(dateMonth)+"-"+dateYear; + + function validaNull(val){ + if(val === null || val == undefined || val == "?"){ + val = "?"; + } else { + val = (parseFloat(val)).toFixed(2); + } + return val; + }; + + function back(){ + if(oType=="proEffic"){ + var oID = $('.dashPro').attr("id"); + var oIDs = oID.split('Item'); + var id = oIDs[0]; + var uid = oIDs[1]; + + if($('.proGreen').hasClass('panel-red')){ + var comparative = -1; + } else if($('.proRed').hasClass('panel-green')){ + var comparative = +1; + } + + proxy.peiData(uid, dateActual, dateActualEnd, + function(dataIndicator){ + indicatorsData(dataIndicator, "proEffic", uid, comparative ); + }); + } else if(oType == "userEffic"){ + var oID = $('.dashUsr').attr("id"); + var oIDs = oID.split('Item'); + var id = oIDs[0]; + var uid = oIDs[1]; + + if($('.proRed').hasClass('panel-red')){ + var comparative = -1; + } else if($('.proRed').hasClass('panel-green')){ + var comparative = +1; + } + + proxy.ueiData(uid, dateActual, dateActualEnd, + function(dataIndicator){ + indicatorsData(dataIndicator, "userEffic", uid, comparative); + }); + } + }; + + /***** Adding Data by indicator *****/ + function indicatorsData(dataIndicator, type, indUid, comparative){ + $('#indicatorsDataGridStack').gridstack(); + var gridIndicators = $('#indicatorsDataGridStack').data('gridstack'), + widgetDetailDom; + gridIndicators.remove_all(); + + var gridProcess = $('#relatedDataGridStack').data('gridstack'); + gridProcess.remove_all(); + + oType = type; + switch (type) { + case 'proEffic': //Process Efficience Index + case 'userEffic': + var widget = proEfficDataGen; + var widgetDetail = proEfficDetail; + type = 'proEffic'; + break; + case 'generalGreat': + var widget = generalDataGreat; + var widgetDetail = ""; + break; + case 'generalLow': + var widget = generalDataLow; + var widgetDetail = ""; + break; + } + + //Drawing + gridIndicators.add_widget($(widget), 0, 15, 20, 4.7, true); //General data + + if(oType == "proEffic" || oType == "userEffic"){ + if(comparative<0){ + $(document.getElementsByClassName("greenbg")).removeClass("greenbg").addClass("redbg"); + $(document.getElementsByClassName("green")).removeClass("green").addClass("red"); + } else if(comparative>=0) { + $(document.getElementsByClassName("redbg")).removeClass("redbg").addClass("greenbg"); + } + } + + if (oType == "generalGreat" || oType == "generalLow") { + document.getElementById("relatedLabel").innerHTML = ""; + var graph1 = null; + if (dataIndicator.graph1Type == '10') { + generalBarParams1.graph.axisX.label = dataIndicator.graph1XLabel; + generalBarParams1.graph.axisY.label = dataIndicator.graph1YLabel; + graph1 = new BarChart(dataIndicator.graph1Data, generalBarParams1, null, null); + } else { + generalLineParams1.graph.axisX.label = dataIndicator.graph1XLabel; + generalLineParams1.graph.axisY.label = dataIndicator.graph1YLabel; + graph1 = new LineChart(dataIndicator.graph1Data, generalLineParams1, null, null); + } + graph1.drawChart(); + + var graph2 = null; + if (dataIndicator.graph2Type == '10') { + generalBarParams2.graph.axisX.label = dataIndicator.graph2XLabel; + generalBarParams2.graph.axisY.label = dataIndicator.graph2YLabel; + graph2 = new BarChart(dataIndicator.graph2Data, generalBarParams2, null, null); + } else { + generalLineParams2.graph.axisX.label = dataIndicator.graph2XLabel; + generalLineParams2.graph.axisY.label = dataIndicator.graph2YLabel; + graph2 = new LineChart(dataIndicator.graph2Data, generalLineParams2, null, null); + } + graph2.drawChart(); + } + + //ProEffic or userEffic + if(type == "proEffic" || type == "userEffic"){ + var inValue = validaNull(dataIndicator.efficiencyIndex); + var inCost = validaNull(dataIndicator.inefficiencyCost); + + document.getElementById(type+"Index").innerHTML = inValue; + document.getElementById(type+"Cost").innerHTML = "$" +inCost; + + //first level draw + if(oType == "proEffic") { + document.getElementById("relatedLabel").innerHTML = "

"+ G_STRING.ID_RELATED_PROCESS +"

"; + var graph = new Pie3DChart(dataIndicator.dataToDraw, peiParams, null, null); + graph.drawChart(); + } + + if(oType == "userEffic") { + document.getElementById("relatedLabel").innerHTML = "

"+ G_STRING.ID_RELATED_GROUPS +"

"; + var graph = new LineChart(dataIndicator.dataToDraw, ueiParams, null, null); + graph.drawChart(); + } + + //Data by process + for (i in dataIndicator.data){ + var proUid = dataIndicator.data[i].uid; + var proDataName = dataIndicator.data[i].name; + var proDataEfficiency = validaNull(dataIndicator.data[i].efficiencyIndex); + var proDataEfficCost = validaNull(dataIndicator.data[i].inefficiencyCost); + var x = 0; + if(i % 2 == 0){ + x = 6; + } + + widgetDetailDom = $(widgetDetail); + widgetDetailDom.attr('id', proUid); + + gridProcess.add_widget(widgetDetailDom, x, 15, 6, 2, true); + + if(comparative<0){ + $(document.getElementsByClassName("green")).removeClass("green").addClass("blue"); + } else if(comparative>=0){ + //$(document.getElementsByClassName("blue")).removeClass("blue").addClass("green"); + } + + if(proDataName.length>25){ + proDataName = proDataName.substring( -25, 25 ); + proDataName = proDataName+"..."; + } + + //charging data by process + //Process Title + $("#procGreyTitle").attr('id', "procGreyTitle"+proUid);//changin the id + document.getElementById("procGreyTitle"+proUid).innerHTML = ""+proDataName+""; + //'+ G_STRING.ID_PRO_EFFICIENCY_INDEX +' + $("#proIndex").attr('id', "proIndex"+proUid);//changin the id + document.getElementById("proIndex"+proUid).innerHTML = proDataEfficiency; + //Process Efficiency Cost + $("#proCost").attr('id', "proCost"+proUid);//changin the id + document.getElementById("proCost"+proUid).innerHTML = proDataEfficCost; + + widgetDetailDom.click(function(e){ + var proid = $(this).attr("id"); + var proname = $(this).find("#procGreyTitle"+proid).html(); + var proindex = validaNull($(this).find("#proIndex"+proid).html()); + var procost = validaNull($(this).find("#proCost"+proid).html()); + + gridIndicators.remove_all(); + gridProcess.remove_all(); + + //Drawing + gridIndicators.add_widget($(proEfficData), 0, 15, 20, 4.7, true); //General data of the process + if(comparative < 0){ + $(document.getElementsByClassName("greenbg")).removeClass("greenbg").addClass("redbg"); + $(document.getElementsByClassName("green")).removeClass("green").addClass("red"); + } else if(comparative > 0){ + $(document.getElementsByClassName("redbg")).removeClass("redbg").addClass("greenbg"); + //$(document.getElementsByClassName("red")).removeClass("red").addClass("green"); + } + + //adding data + //var name = $("#"+oType+"Span"+indUid).html(); + document.getElementById(type+"Title").innerHTML = name; + document.getElementById("proDetName").innerHTML = proname; + document.getElementById(type+"Index").innerHTML = proindex; + document.getElementById(type+"Cost").innerHTML = "$" +procost; + + //adding tasks + if(oType == "proEffic"){ + proxy.processTasksData(proid, dateActual, dateActualEnd, + function(dataTasks){ + tasksData(dataTasks, gridProcess, proid); + hideScrollIfAllDivsAreVisible(); + }); + } else { + proxy.userGroupData(proid, dateActual, dateActualEnd, + function(dataTasks){ + tasksData(dataTasks, gridProcess, proid); + hideScrollIfAllDivsAreVisible(); + }); + } + return false; + }); + } + hideScrollIfAllDivsAreVisible(); + } + //Adding the data by process + var name = $("#"+oType+"Span"+indUid).html(); + document.getElementById(type+"Title").innerHTML = name; + }; + + function tasksData(dataTasks, gridIndicators, proid){ + var i = 0; + if(oType == "proEffic"){ + document.getElementById("relatedLabel").innerHTML = "

"+ G_STRING.ID_RELATED_TASKS +"

"; + var graph = new LineChart(dataTasks.dataToDraw, peiDetailParams, null, null); + graph.drawChart(); + for (i in dataTasks.tasksData){ + var taskUid = dataTasks.tasksData[i].uid; + var taskName = dataTasks.tasksData[i].name; + var taskEffic = validaNull(dataTasks.tasksData[i].efficienceIndex); + var taskAverage = validaNull(dataTasks.tasksData[i].averageTime); + var taskDeviation = validaNull(dataTasks.tasksData[i].deviationTime); + var x = 0; + if(i % 2 == 0){ + x = 6; + } + + var widgetDetailTaskDom = $(proEfficTaskDetail); + widgetDetailTaskDom.attr('id', taskUid+"task"); + gridIndicators.add_widget(widgetDetailTaskDom, x, 15, 6, 2, true);//Drawing the task + + if($('.proGreen').hasClass('panel-red')){ + $(document.getElementsByClassName("greenbg")).removeClass("greenbg").addClass("redbg"); + }else { + $(document.getElementsByClassName("redbg")).removeClass("redbg").addClass("greenbg"); + } + + if(taskName.length>55){ + taskName = taskName.substring( -55, 55 ); + taskName = taskName+"..."; + } + + //Adding data to task + //Task Title + $("#taskName").attr('id', "taskName"+taskUid);//changin the id + document.getElementById("taskName"+taskUid).innerHTML = taskName; + //Task Efficiency Index + $("#taskEffic").attr('id', "taskEffic"+taskUid);//changin the id + document.getElementById("taskEffic"+taskUid).innerHTML = taskEffic; + //Task Average + $("#taskAver").attr('id', "taskAver"+taskUid);//changin the id + document.getElementById("taskAver"+taskUid).innerHTML = taskAverage; + //Task Deviation + $("#taskDeviat").attr('id', "taskDeviat"+taskUid);//changin the id + document.getElementById("taskDeviat"+taskUid).innerHTML = taskDeviation; + } + } else { + document.getElementById("relatedLabel").innerHTML = "

"+ G_STRING.ID_RELATED_USERS +"

"; + var graph = new LineChart(dataTasks.dataToDraw, ueiDetailParams, null, null); + graph.drawChart(); + for (i in dataTasks.tasksData){ + var usrUid = dataTasks.tasksData[i].userUid; + var usrName = dataTasks.tasksData[i].name; + var usrEffic = validaNull(dataTasks.tasksData[i].efficiencyIndex); + var usrCost = validaNull(dataTasks.tasksData[i].inefficiencyCost); + var x = 0; + if(i % 2 == 0){ + x = 6; + } + + var widgetDetailUsrDom = $(userTaskDetail); + widgetDetailUsrDom.attr('id', usrUid+"task"); + gridIndicators.add_widget(widgetDetailUsrDom, x, 15, 6, 2, true);//Drawing the task + + if($('.proRed').hasClass('panel-green')){ + $(document.getElementsByClassName("redbg")).removeClass("redbg").addClass("greenbg"); + } else{ + $(document.getElementsByClassName("greenbg")).removeClass("greenbg").addClass("redbg"); + } + + if(usrName.length>55){ + usrName = usrName.substring( -55, 55 ); + usrName = usrName+"..."; + } + + //Adding data to task + //Task Title + $("#usrName").attr('id', "usrName"+usrUid);//changin the id + document.getElementById("usrName"+usrUid).innerHTML = usrName; + //Task Efficiency Index + $("#usrEffic").attr('id', "usrEffic"+usrUid);//changin the id + document.getElementById("usrEffic"+usrUid).innerHTML = usrEffic; + //Task Deviation + $("#usrCost").attr('id', "usrCost"+usrUid);//changin the id + document.getElementById("usrCost"+usrUid).innerHTML = usrCost; + } + } + + + }; + + function hideScrollIfAllDivsAreVisible(){ + console.log('ocultos ' + $('.hideme').length); + if ($('.hideme').length <= 0) { + $('#theImg').hide(); + } + else { + $('#theImg').show(); + } + } + + $( document ).ready(function() { + /* Show on scroll functionality... */ + $(window).scroll( function() { + /* Check the location of each desired element */ + $('.hideme').each( function(i){ + var bottom_of_object = $(this).offset().top + $(this).outerHeight(); + var bottom_of_window = $(window).scrollTop() + $(window).height(); + /* If the object is completely visible in the window, fade it in */ + if (bottom_of_window + 100 > bottom_of_object) { + $(this).animate({'opacity':'1'}, 500); + $(this).removeClass('hideme'); + } + }); + hideScrollIfAllDivsAreVisible(); + }); + + if(dateMonth == 0){ + document.getElementById('year').selectedIndex = 1; + document.getElementById('mounth').selectedIndex = 11; + }else{ + document.getElementById('mounth').selectedIndex = dateMonth-1; + } + + /*****calling the proxy*****/ + function getDashboardProxy(type) { + var ws = urlProxy.split('/'); + if (type.toLowerCase()=='test') + return new DashboardProxyTest(); + + if (type.toLowerCase()=='pro') + return new DashboardProxy(token, + urlProxy, + ws[3]); + }; + proxy = getDashboardProxy('pro'); + proxy.userDashboards(usrId, + function(dataDashboards){ + if(dataDashboards.length > 0){ + dashboardsButtons(dataDashboards); + }else{ + $(".indicators").append("

"+ G_STRING.ID_GRID_PAGE_NO_DASHBOARD_MESSAGE +"

"); + } + }); + + /*********************************/ + //ConfigurationObject + objConfigDashboards = [ + { + "dashUid": "15115651654654", + "favorite": 1, + "indicators":[ + { + /*"indUid": "15115651654654", + "indName": "Process Efficiency Index",*/ + "id": "proEffic", + "favorite": 1, + "x": 0, + "y": 6, + "height": "50px", + "width": "20px" + }, { + /*"indUid": "45165165165161", + "indName": "Completed Cases",*/ + "id": "compCases", + "favorite": 0, + "x": 6, + "y": 6, + "height": "50px", + "width": "20px" + } + ] + }, + { + "dashUid": "5645565165465", + "favorite": 0, + "indicators":[ + { + /*"indUid": "15115651654654", + "indName": "Number Cases",*/ + "id": "numCases", + "favorite": 0, + "x": 0, + "y": 6, + "height": "50px", + "width": "20px" + }, { + /*"indUid": "45165165165161", + "indName": "User Efficiency",*/ + "id": "userEffic", + "favorite": 1, + "x": 4, + "y": 6, + "height": "50px", + "width": "20px" + }, + { + /*"indUid": "45165165165161", + "indName": "Completed Cases",*/ + "id": "compCases", + "favorite": 0, + "x": 8, + "y": 6, + "height": "50px", + "width": "20px" + } + ] + } + ]; + + //When some item is moved + $('.grid-stack').on('change', function (e, items) { + var widgets = []; + _.map($('.grid-stack .grid-stack-item:visible'), function (el) { + el = $(el); + var item = el.data('_gridstack_node'); + var idWidGet = item.el[0].id.split('Item'); + if(favorite == actualDashId){ + favoriteData = 1; + } else { + favoriteData = 0; + } + if (typeof idWidGet[1] != "undefined") { + var widgetsObj = { + 'indicatorId': idWidGet[1], + 'x': item.x, + 'y': item.y, + 'width': item.width, + 'height': item.height <= 1 ? 2 : item.height + } + widgets.push(widgetsObj); + } + }); + + if (widgets.length != 0) { + var dashboard = { + 'dashId': actualDashId, + 'dashFavorite': favoriteData, + 'dashData': widgets + } + proxy.setPositionIndicator(dashboard); + } + }); + + + /*****Adding Buttons*****/ + function dashboardsButtons(dataDashboards){ + for( i in dataDashboards){ + var dashUid = dataDashboards[i].dashUid; + var dashName = dataDashboards[i].dashName; + var dashFavorite = dataDashboards[i].favorite; + + var domButton = $(dasButton); + + //adding a new button + $( "#dasbuttons" ).append( domButton ); + + //adding the UID like the id of the tag. + $("#dasB").attr('id', dashUid); + $("#favorite").attr('id', dashUid+'fav'); + + if(dashName.length>20){ + dashNameButton = dashName.substring( -20, 20 ); + dashNameButton = dashNameButton+"..."; + } else{ + dashNameButton = dashName; + } + + //addign the name + document.getElementById(dashUid).innerHTML = dashNameButton; + + //if it is favorite adding the selected class + if(dashFavorite == 1){ + actualDashId = dashUid; + favorite = actualDashId; + document.getElementById("titleH4").innerHTML = dashName; + $("#"+dashUid+"fav").addClass("selected"); + + //calling backend + proxy.dashboardIndicators(dashUid, dateActual, dateActualEnd, + function(widgetsObj) { + indicators(widgetsObj); + }); + } + + domButton.find("#"+dashUid+"fav").click(function() { + dashUid = $(this).siblings('.btn').attr("id"); + favorite = dashUid; + + $(".selected").removeClass("selected"); + $(this).addClass("selected"); + //call backend to save the favorite selection + var dashboard = { + 'dashId': dashUid, + 'dashFavorite': 1, + 'dashData': '' + } + proxy.setPositionIndicator(dashboard); + }); + + domButton.find("#"+dashUid).click(function() { + var btnid = $(this).attr("id"); + //first we have to get the divs empty + $('#indicatorsGridStack').gridstack(); + var gridDashboards = $('#indicatorsGridStack').data('gridstack'); + gridDashboards.remove_all(); + + $('#indicatorsDataGridStack').gridstack(); + var gridIndicators = $('#indicatorsDataGridStack').data('gridstack'); + gridIndicators.remove_all(); + + //changing the Name of the Dashboard + var btnName = $(this).html(); + document.getElementById("titleH4").innerHTML = btnName; + + actualDashId = btnid; + //calling backend + proxy.dashboardIndicators(btnid, dateActual, dateActualEnd, + function(widgetsObj) { + indicators(widgetsObj); + }); + }); + + } + }; + + + + /*****Adding the indicators*****/ + function indicators (widgetsObj){ + $('#indicatorsGridStack').gridstack(); + + serialization = GridStackUI.Utils.sort(widgetsObj); + var grid = $('#indicatorsGridStack').data('gridstack'); + //var width = 12 / widgetsObj.length; + var i = 1; + + _.each(serialization, function (node) { + if(node.x == 0){ + var x = 12 - (12/i); + }else { + var x = node.x; + } + if(node.y == 0){ + var y = 6; + }else { + var y = node.y; + } + + if(node.height == 0){ + node.height = 2; + } + if(node.width == 0){ + node.width = 12 / widgetsObj.length; + } + + node.comparative = validaNull(node.comparative); + + switch (node.id) { + case "1010": //Process Efficience Index + var widget = proEffic; + var id = "proEffic"; + break; + case "1030": //Employee Efficience Index + var widget = userEffic; + var id = "userEffic"; + break; + case "1050": + case "1060": + case "1070": + case "1080": + var indexI = parseFloat(node.index); + var comparativeI = parseFloat(node.comparative); + var condition = (node.direction == "1")? (indexI <= comparativeI) : (indexI >= comparativeI); + if(condition == true){ + var widget = numCases; //Great + var id = "generalGreat"; + } else { + var widget = compCases; //Low + var id = "generalLow"; + } + break; + } + + //var comparative = (parseFloat(node.comparative)).toFixed(2); + var widgetDom = $(widget); + + //Dibujando + grid.add_widget(widgetDom, x, y, node.width, node.height, true); //dibuja los elementos + + $("#"+id+"Item").attr('id', id+"Item"+node.indUid);//changin the id of the divs + $("#"+id+"Div").attr('id', id+"Div"+node.indUid); + $("#"+id+"Huge").attr('id', id+"Huge"+node.indUid); + $("#"+id+"Small").attr('id', id+"Small"+node.indUid); + $("#"+id+"M").attr('id', id+"M"+node.indUid); + $("#"+id+"Span").attr('id', id+"Span"+node.indUid); + + if(id =="generalGreat" || id == "generalLow"){ + $("#"+id).attr('id', id+node.indUid); + } + + //Showing the data panels if is the favorite + if(node.favorite == 1){ + //changing the class + if ($("#"+id+"M"+node.indUid).hasClass('panel-active')){ + //nada + }else{ + //changing classes to show selection + $(document.getElementsByClassName("panel-active")).removeClass("panel-active"); + $("#"+id+"M"+node.indUid).addClass("panel-active"); + } + + //Getting the data + if(id == "proEffic"){ + proxy.peiData(node.indUid, dateActual, dateActualEnd, + function(dataIndicator){ + indicatorsData(dataIndicator, "proEffic", node.indUid, node.comparative); + hideScrollIfAllDivsAreVisible(); + }); + } else if (id == "userEffic" ){ + proxy.ueiData(node.indUid, dateActual, dateActualEnd, + function(dataIndicator){ + indicatorsData(dataIndicator, "userEffic", node.indUid, node.comparative); + hideScrollIfAllDivsAreVisible(); + }); + } else { + proxy.generalIndicatorData(node.indUid, dateActual, dateActualEnd, + function(dataIndicator){ + var indexI = parseFloat(node.index); + var comparativeI = parseFloat(node.comparative); + var condition = (node.direction == "1")? (indexI <= comparativeI) : (indexI >= comparativeI); + if(condition == true){ //this are percentages + indicatorsData(dataIndicator, "generalGreat", node.indUid, node.comparative); + hideScrollIfAllDivsAreVisible(); + } else{ + indicatorsData(dataIndicator, "generalLow", node.indUid, node.comparative); + hideScrollIfAllDivsAreVisible(); + } + }); + } + } else { + $("#"+id+"M"+node.indUid).removeClass("panel-active"); + } + + //Animating the Indicators + animateprogress(id, node.index, node.comparative, node.indName, node.indUid, node.direction); //inserta datos en cada elemento + i++; + + hideScrollIfAllDivsAreVisible(); + /********Changing the class when the indicator item is selected********/ + widgetDom.click(function(){ + var oID = $(this).attr("id"); + + if(oID != undefined && oID.indexOf('Item') != -1){ + var comparative = 0; + var oIDs = oID.split('Item'); + var id = oIDs[0]; + var uid = oIDs[1]; + + if($(this).children().hasClass('panel-red')){ + var comparative = -1; + } else if($(this).children().hasClass('panel-green')){ + var comparative = +1; + } + + /*if ($("#"+id+"M"+uid).hasClass('panel-active')){ + //nada + }else{*/ + //changing classes to show selection + $(document.getElementsByClassName("panel-active")).removeClass("panel-active"); + $("#"+id+"M"+uid).addClass("panel-active"); + + //calling data of the indicator + if(id == "proEffic"){ + proxy.peiData(uid, dateActual, dateActualEnd, + function(dataIndicator){ + indicatorsData(dataIndicator, "proEffic", uid, comparative); + hideScrollIfAllDivsAreVisible(); + }); + } else if (id == "userEffic" ){ + proxy.ueiData(uid, dateActual, dateActualEnd, + function(dataIndicator){ + indicatorsData(dataIndicator, "userEffic", uid, comparative); + hideScrollIfAllDivsAreVisible(); + }); + } else { + proxy.generalIndicatorData(uid, dateActual, dateActualEnd, + function(dataIndicator){ + var index = $("#"+id+"Huge"+uid).html(); + index = parseInt(index); + var indexI = parseFloat(node.index); + var comparativeI = parseFloat(node.comparative); + var condition = (node.direction == "1")? (indexI <= comparativeI) : (indexI >= comparativeI); + if(condition == true){ //this are percentages + indicatorsData(dataIndicator, "generalGreat", uid, comparative); + } else{ + indicatorsData(dataIndicator, "generalLow", uid, comparative); + } + hideScrollIfAllDivsAreVisible(); + }); + } + + //} + } + }); + }); + }; + + $(".btn-compare").click(function(){ + var yearComp = $( "#year option:selected" ).text(); + var mounthComp = $( "#mounth option:selected" ).val(); + + dateActualEnd = "30-"+(mounthComp)+"-"+yearComp; + + //first we have to get the divs empty + $('#indicatorsGridStack').gridstack(); + var gridDashboards = $('#indicatorsGridStack').data('gridstack'); + gridDashboards.remove_all(); + + $('#indicatorsDataGridStack').gridstack(); + var gridIndicators = $('#indicatorsDataGridStack').data('gridstack'); + gridIndicators.remove_all(); + console.log(dateActualEnd); + //calling backend + proxy.dashboardIndicators(actualDashId, dateActual, dateActualEnd, + function(widgetsObj) { + indicators(widgetsObj); + }); + }); + + + }); + +$(function () { + var options = { + cell_height: 75, + vertical_margin: 12 + }; + $('.grid-stack').gridstack(options); +}); \ No newline at end of file diff --git a/workflow/engine/js/strategicDashboard/dashboardProxy.js b/workflow/engine/js/strategicDashboard/dashboardProxy.js new file mode 100644 index 000000000..2f8458174 --- /dev/null +++ b/workflow/engine/js/strategicDashboard/dashboardProxy.js @@ -0,0 +1,502 @@ + +var getKeyValue = +function getKeyValue(obj, key, undefined) { + var reg = /\./gi + , subKey + , keys + , context + , x + ; + + if (reg.test(key)) { + keys = key.split(reg); + context = obj; + + for (x = 0; x < keys.length; x++) { + subKey = keys[x]; + + //the values of all keys except for + //the last one should be objects + if (x < keys.length -1) { + if (!context.hasOwnProperty(subKey)) { + return undefined; + } + + context = context[subKey]; + } + else { + return context[subKey]; + } + } + } + else { + return obj[key]; + } +}; + +var setKeyValue = +function setKeyValue(obj, key, value) { + var reg = /\./gi + , subKey + , keys + , context + , x + ; + + //check to see if we need to process + //multiple levels of objects + if (reg.test(key)) { + keys = key.split(reg); + context = obj; + + for (x = 0; x < keys.length; x++) { + subKey = keys[x]; + + //the values of all keys except for + //the last one should be objects + if (x < keys.length -1) { + if (!context[subKey]) { + context[subKey] = {}; + } + + context = context[subKey]; + } + else { + context[subKey] = value; + } + } + } + else { + obj[key] = value; + } +}; + +var merge = +function merge(objFrom, objTo, propMap) { + var toKey + , fromKey + , x + , value + , def + , transform + , key + , keyIsArray + ; + + if (!objTo) { + objTo = {}; + } + + for(fromKey in propMap) { + if (propMap.hasOwnProperty(fromKey)) { + toKey = propMap[fromKey]; + + //force toKey to an array of toKeys + if (!Array.isArray(toKey)) { + toKey = [toKey]; + } + + for(x = 0; x < toKey.length; x++) { + def = null; + transform = null; + key = toKey[x]; + keyIsArray = Array.isArray(key); + + if (typeof(key) === "object" && !keyIsArray) { + def = key.default || null; + transform = key.transform || null; + key = key.key; + //evaluate if the new key is an array + keyIsArray = Array.isArray(key); + } + + if (keyIsArray) { + //key[toKeyName,transform,default] + def = key[2] || null; + transform = key[1] || null; + key = key[0]; + } + + if (def && typeof(def) === "function" ) { + def = def(objFrom, objTo); + } + + value = getKeyValue(objFrom, fromKey); + + if (transform) { + value = transform(value, objFrom, objTo); + } + + if (typeof value !== 'undefined') { + setKeyValue(objTo, key, value); + } + else if (typeof def !== 'undefined') { + setKeyValue(objTo, key, def); + } + } + } + } + + return objTo; +}; + +var DashboardProxy = function (oauthToken, server, workspace) { + this.server = server; + this.workspace = workspace; + this.baseUrl = "/api/1.0/" + workspace + "/"; + this.oauthToken = oauthToken; +}; + +DashboardProxy.prototype.userDashboards = function(userId, callBack) { + this.getJson('dashboard/ownerData/' + userId, + function (r) { + var returnList = []; + $.each(r, function(index, originalObject) { + var map = { + "DAS_TITLE" : "dashName", + "DAS_UID" : "dashUid", + "DAS_FAVORITE" : "favorite", + }; + + var newObject = merge(originalObject, {}, map); + returnList.push(newObject); + }); + callBack(returnList); + }); +}; + +DashboardProxy.prototype.dashboardIndicators = function(dashboardId, initDate, endDate, callBack) { + this.getJson('dashboard/' + dashboardId + '/indicator?dateIni=' + initDate + '&dateFin=' + endDate, + function (r) { + var returnList = []; + $.each(r, function(index, originalObject) { + var map = { + "DAS_IND_UID" : "indUid", + "DAS_IND_TITLE" : "indName", + "DAS_IND_TYPE" : "id", + "DAS_IND_VARIATION" : "comparative", + "DAS_IND_DIRECTION" : "direction", + "DAS_IND_VALUE" : "index", + "DAS_IND_X" : "x", + "DAS_IND_Y" : "y", + "DAS_IND_WIDTH" : "width", + "DAS_IND_HEIGHT" : "height", + "DAS_UID_PROCESS" : "process" + }; + + var newObject = merge(originalObject, {}, map); + //TODO do not burn this value. Data must come from the endpoint + newObject.favorite = ((returnList.length == 1) ? 1 : 0); + returnList.push(newObject); + }); + callBack(returnList); + }); +}; + +DashboardProxy.prototype.peiData = function(indicatorId, measureDate, compareDate, callBack) { + var endPoint = "ReportingIndicators/process-efficiency-data?" + + "indicator_uid=" + indicatorId + + "&measure_date=" + measureDate + + "&compare_date=" + compareDate + + "&language=en"; + this.getJson(endPoint, + function (r) { + var graphData = []; + $.each(r.data, function(index, originalObject) { + var map = { + "name" : "datalabel", + "inefficiencyCost" : "value" + }; + var newObject = merge(originalObject, {}, map); + var shortLabel = (newObject.datalabel == null) + ? "" + : newObject.datalabel.substring(0,15); + newObject.datalabel = shortLabel; + graphData.push(newObject); + }); + r.dataToDraw = graphData.splice(0,7); + callBack(r); + }); +} + +DashboardProxy.prototype.processTasksData = function(process, initDate, endDate, callBack) { + var endPoint = "ReportingIndicators/process-tasks?" + + "process_list=" + process + + "&init_date=" + initDate + + "&end_date=" + endDate + + "&language=en"; + this.getJson(endPoint, + function (r) { + var graphData = []; + $.each(r, function(index, originalObject) { + var map = { + "name" : "datalabel", + "averageTime" : "value", + "deviationTime" : "dispersion" + }; + var newObject = merge(originalObject, {}, map); + newObject.datalabel = newObject.datalabel.substring(0, 7); + graphData.push(newObject); + }); + var retval = {}; + retval.dataToDraw = graphData.splice(0,7); + retval.tasksData = r; + callBack(retval); + }); +} + +DashboardProxy.prototype.ueiData = function(indicatorId, measureDate, compareDate, callBack) { + var endPoint = "ReportingIndicators/employee-efficiency-data?" + + "indicator_uid=" + indicatorId + + "&measure_date=" + measureDate + + "&compare_date=" + compareDate + + "&language=en"; + this.getJson(endPoint, + function (r) { + var graphData = []; + $.each(r.data, function(index, originalObject) { + var map = { + "name" : "datalabel", + "averageTime" : "value", + "deviationTime" : "dispersion" + }; + var newObject = merge(originalObject, {}, map); + var shortLabel = (newObject.datalabel == null) + ? "" + : newObject.datalabel.substring(0,7); + + newObject.datalabel = shortLabel; + graphData.push(newObject); + }); + r.dataToDraw = graphData.splice(0,7); + callBack(r); + }); + + /*var retval = { + "efficiencyIndex":1.23, + "efficiencyVariation":0.23, + "inefficiencyCost":"$ 20112.23", + "employeeGroupsDataToDraw": + [ + {"value":"96", "datalabel":"User 1"}, + {"value":"84", "datalabel":"User 2"}, + {"value":"72", "datalabel":"User 3"}, + {"value":"18", "datalabel":"User 4"}, + {"value":"85", "datalabel":"User 5"} + ], + + "employeeGroupsData": [ + {"name": "User 1", "efficiencyIndex":"0.45", "innefficiencyCost":"$ 3404"}, + {"name": "User 2", "efficiencyIndex":"1.45", "innefficiencyCost":"$ 1404"}, + {"name": "User 3", "efficiencyIndex":"0.25", "innefficiencyCost":"$ 3304"}, + {"name": "User 4", "efficiencyIndex":"1.95", "innefficiencyCost":"$ 404"}, + {"name": "User 5", "efficiencyIndex":"1.25", "innefficiencyCost":"$ 13404"}, + {"name": "User 6", "efficiencyIndex":"0.75", "innefficiencyCost":"$ 4"} + ] + } + return retval;*/ +} + +DashboardProxy.prototype.userGroupData = function(groupId, initDate, endDate, callBack) { + var endPoint = "ReportingIndicators/group-employee-data?" + + "group_uid=" + groupId + + "&init_date=" + initDate + + "&end_date=" + endDate + + "&language=en"; + this.getJson(endPoint, + function (r) { + var graphData = []; + $.each(r, function(index, originalObject) { + var map = { + "name" : "datalabel", + "averageTime" : "value", + "deviationTime" : "dispersion" + }; + var newObject = merge(originalObject, {}, map); + newObject.datalabel = newObject.datalabel.substring(0, 7); + graphData.push(newObject); + }); + var retval = {}; + retval.dataToDraw = graphData.splice(0,7); + retval.tasksData = r; + callBack(retval); + }); +} + +DashboardProxy.prototype.generalIndicatorData = function(indicatorId, initDate, endDate, callBack) { + var method = ""; + var endPoint = "ReportingIndicators/general-indicator-data?" + + "indicator_uid=" + indicatorId + + "&init_date=" + initDate + + "&end_date=" + endDate + + "&language=en"; + this.getJson(endPoint, + function (r) { + $.each(r.graph1Data, function(index, originalObject) { + var label = (('YEAR' in originalObject) ? originalObject.YEAR : "") ; + label += (('MONTH' in originalObject) ? "/" + originalObject.MONTH : "") ; + label += (('QUARTER' in originalObject) ? "/" + originalObject.QUARTER : ""); + label += (('SEMESTER' in originalObject) ? "/" + originalObject.SEMESTER : ""); + originalObject.datalabel = label; + }); + + $.each(r.graph2Data, function(index, originalObject) { + var label = (('YEAR' in originalObject) ? originalObject.YEAR : "") ; + label += (('MONTH' in originalObject) ? "/" + originalObject.MONTH : "") ; + label += (('QUARTER' in originalObject) ? "/" + originalObject.QUARTER : ""); + label += (('SEMESTER' in originalObject) ? "/" + originalObject.SEMESTER : "") ; + originalObject.datalabel = label; + }); + callBack(r); + }); + + + + /*var retval = { + "index" : "23", + "graph1Data": [ + {"value":"96", "datalabel":"User 1"}, + {"value":"84", "datalabel":"User 2"}, + {"value":"72", "datalabel":"User 3"}, + {"value":"18", "datalabel":"User 4"}, + {"value":"85", "datalabel":"User 5"} + ], + "graph2Data": [ + {"value":"196", "datalabel":"User 1"}, + {"value":"184", "datalabel":"User 2"}, + {"value":"172", "datalabel":"User 3"}, + {"value":"118", "datalabel":"User 4"}, + {"value":"185", "datalabel":"User 5"} + ] + } + return retval;*/ +} + +DashboardProxy.prototype.userTasksData = function(processId, monthCompare, yearCompare) { + var retval = { + "tasksDataToDraw": [ + {"value":"96", "datalabel":"Task 1"}, + {"value":"84", "datalabel":"Task 2"}, + {"value":"72", "datalabel":"Task 3"}, + {"value":"18", "datalabel":"Task 4"}, + {"value":"85", "datalabel":"Task 5"} + ], + + "tasksData": [ + {"Name": "Task 1", "efficiencyIndex":"0.45", "deviationTime":"0.45", "averageTime":"34 days"}, + {"Name": "Task 2", "efficiencyIndex":"1.45", "deviationTime":"1.45", "averageTime":"14 days"}, + {"Name": "Task 3", "efficiencyIndex":"0.25", "deviationTime":"0.25", "averageTime":"3 days"}, + {"Name": "Task 4", "efficiencyIndex":"1.95", "deviationTime":"1.95", "averageTime":"4 days"}, + {"Name": "Task 5", "efficiencyIndex":"1.25", "deviationTime":"1.25", "averageTime":"14 days"}, + {"Name": "Task 6", "efficiencyIndex":"0.75", "deviationTime":"0.75", "averageTime":"4 days"} + ] + + } + return retval; +} + +DashboardProxy.prototype.getPositionIndicator = function(callBack) { + console.log("GET"); + this.getJson('dashboard/config', function (r) { + var graphData = []; + $.each(r, function(index, originalObject) { + console.log(originalObject); + var map = { + "widgetId" : originalObject.widgetId, + "x" : originalObject.x, + "y" : originalObject.y, + "width" : originalObject.width, + "height" : originalObject.height + + }; + graphData.push(map); + }); + callBack(graphData); + }); +}; + +DashboardProxy.prototype.setPositionIndicator = function(data, callBack) { + var that = this; + + this.getPositionIndicator( + function(response){ + if (response.length != 0) { + that.putJson('dashboard/config', data, function (r) { + }); + } else { + that.postJson('dashboard/config', data, function (r) { + }); + } + } + ); +}; + + + +DashboardProxy.prototype.getJson = function (endPoint, callBack) { + var that = this; + var callUrl = this.baseUrl + endPoint + console.log('Llamando:'); + console.log(callUrl) + $.ajax({ + url: callUrl, + type: 'GET', + datatype: 'json', + success: function(response) { callBack(response); }, + error: function(jqXHR, textStatus, errorThrown) { + console.log(textStatus, errorThrown); + }, + beforeSend: function (xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + that.oauthToken); + xhr.setRequestHeader('Access-Control-Allow-Origin', '*'); + } + + }); +} + +DashboardProxy.prototype.postJson = function (endPoint, data, callBack) { + var that = this; + $.ajax({ + url : this.baseUrl + endPoint, + type : 'POST', + datatype : 'json', + contentType: "application/json; charset=utf-8", + data: JSON.stringify(data), + success: function(response) { + callBack(response); + }, + error: function(jqXHR, textStatus, errorThrown) { + console.log(textStatus, errorThrown); + }, + beforeSend: function (xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + that.oauthToken); + xhr.setRequestHeader('Access-Control-Allow-Origin', '*'); + } + }).fail(function () { + console.log('Fail server'); + }); +}; + + +DashboardProxy.prototype.putJson = function (endPoint, data, callBack) { + var that = this; + $.ajax({ + url : this.baseUrl + endPoint, + type : 'PUT', + datatype : 'json', + contentType: "application/json; charset=utf-8", + data: JSON.stringify(data), + success: function(response) { + callBack(response); + }, + error: function(jqXHR, textStatus, errorThrown) { + console.log(textStatus, errorThrown); + }, + beforeSend: function (xhr) { + xhr.setRequestHeader('Authorization', 'Bearer ' + that.oauthToken); + xhr.setRequestHeader('Access-Control-Allow-Origin', '*'); + } + }).fail(function () { + console.log('Fail server'); + }); +}; diff --git a/workflow/engine/js/strategicDashboard/underscore.js b/workflow/engine/js/strategicDashboard/underscore.js new file mode 100644 index 000000000..afd92e5bb --- /dev/null +++ b/workflow/engine/js/strategicDashboard/underscore.js @@ -0,0 +1,1416 @@ +// Underscore.js 1.7.0 +// http://underscorejs.org +// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.7.0'; + + // Internal function that returns an efficient (for current engines) version + // of the passed-in callback, to be repeatedly applied in other Underscore + // functions. + var createCallback = function(func, context, argCount) { + if (context === void 0) return func; + switch (argCount == null ? 3 : argCount) { + case 1: return function(value) { + return func.call(context, value); + }; + case 2: return function(value, other) { + return func.call(context, value, other); + }; + case 3: return function(value, index, collection) { + return func.call(context, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(context, accumulator, value, index, collection); + }; + } + return function() { + return func.apply(context, arguments); + }; + }; + + // A mostly-internal function to generate callbacks that can be applied + // to each element in a collection, returning the desired result — either + // identity, an arbitrary callback, a property matcher, or a property accessor. + _.iteratee = function(value, context, argCount) { + if (value == null) return _.identity; + if (_.isFunction(value)) return createCallback(value, context, argCount); + if (_.isObject(value)) return _.matches(value); + return _.property(value); + }; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles raw objects in addition to array-likes. Treats all + // sparse array-likes as if they were dense. + _.each = _.forEach = function(obj, iteratee, context) { + if (obj == null) return obj; + iteratee = createCallback(iteratee, context); + var i, length = obj.length; + if (length === +length) { + for (i = 0; i < length; i++) { + iteratee(obj[i], i, obj); + } + } else { + var keys = _.keys(obj); + for (i = 0, length = keys.length; i < length; i++) { + iteratee(obj[keys[i]], keys[i], obj); + } + } + return obj; + }; + + // Return the results of applying the iteratee to each element. + _.map = _.collect = function(obj, iteratee, context) { + if (obj == null) return []; + iteratee = _.iteratee(iteratee, context); + var keys = obj.length !== +obj.length && _.keys(obj), + length = (keys || obj).length, + results = Array(length), + currentKey; + for (var index = 0; index < length; index++) { + currentKey = keys ? keys[index] : index; + results[index] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. + _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) { + if (obj == null) obj = []; + iteratee = createCallback(iteratee, context, 4); + var keys = obj.length !== +obj.length && _.keys(obj), + length = (keys || obj).length, + index = 0, currentKey; + if (arguments.length < 3) { + if (!length) throw new TypeError(reduceError); + memo = obj[keys ? keys[index++] : index++]; + } + for (; index < length; index++) { + currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + _.reduceRight = _.foldr = function(obj, iteratee, memo, context) { + if (obj == null) obj = []; + iteratee = createCallback(iteratee, context, 4); + var keys = obj.length !== + obj.length && _.keys(obj), + index = (keys || obj).length, + currentKey; + if (arguments.length < 3) { + if (!index) throw new TypeError(reduceError); + memo = obj[keys ? keys[--index] : --index]; + } + while (index--) { + currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var result; + predicate = _.iteratee(predicate, context); + _.some(obj, function(value, index, list) { + if (predicate(value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + if (obj == null) return results; + predicate = _.iteratee(predicate, context); + _.each(obj, function(value, index, list) { + if (predicate(value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, _.negate(_.iteratee(predicate)), context); + }; + + // Determine whether all of the elements match a truth test. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + if (obj == null) return true; + predicate = _.iteratee(predicate, context); + var keys = obj.length !== +obj.length && _.keys(obj), + length = (keys || obj).length, + index, currentKey; + for (index = 0; index < length; index++) { + currentKey = keys ? keys[index] : index; + if (!predicate(obj[currentKey], currentKey, obj)) return false; + } + return true; + }; + + // Determine if at least one element in the object matches a truth test. + // Aliased as `any`. + _.some = _.any = function(obj, predicate, context) { + if (obj == null) return false; + predicate = _.iteratee(predicate, context); + var keys = obj.length !== +obj.length && _.keys(obj), + length = (keys || obj).length, + index, currentKey; + for (index = 0; index < length; index++) { + currentKey = keys ? keys[index] : index; + if (predicate(obj[currentKey], currentKey, obj)) return true; + } + return false; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (obj.length !== +obj.length) obj = _.values(obj); + return _.indexOf(obj, target) >= 0; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matches(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matches(attrs)); + }; + + // Return the maximum element (or element-based computation). + _.max = function(obj, iteratee, context) { + var result = -Infinity, lastComputed = -Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = obj.length === +obj.length ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value > result) { + result = value; + } + } + } else { + iteratee = _.iteratee(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed > lastComputed || computed === -Infinity && result === -Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iteratee, context) { + var result = Infinity, lastComputed = Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = obj.length === +obj.length ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value < result) { + result = value; + } + } + } else { + iteratee = _.iteratee(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed < lastComputed || computed === Infinity && result === Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Shuffle a collection, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var set = obj && obj.length === +obj.length ? obj : _.values(obj); + var length = set.length; + var shuffled = Array(length); + for (var index = 0, rand; index < length; index++) { + rand = _.random(0, index); + if (rand !== index) shuffled[index] = shuffled[rand]; + shuffled[rand] = set[index]; + } + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (obj.length !== +obj.length) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // Sort the object's values by a criterion produced by an iteratee. + _.sortBy = function(obj, iteratee, context) { + iteratee = _.iteratee(iteratee, context); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iteratee(value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iteratee, context) { + var result = {}; + iteratee = _.iteratee(iteratee, context); + _.each(obj, function(value, index) { + var key = iteratee(value, index, obj); + behavior(result, value, key); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, value, key) { + if (_.has(result, key)) result[key].push(value); else result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, value, key) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, value, key) { + if (_.has(result, key)) result[key]++; else result[key] = 1; + }); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iteratee, context) { + iteratee = _.iteratee(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = array.length; + while (low < high) { + var mid = low + high >>> 1; + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return obj.length === +obj.length ? obj.length : _.keys(obj).length; + }; + + // Split a collection into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(obj, predicate, context) { + predicate = _.iteratee(predicate, context); + var pass = [], fail = []; + _.each(obj, function(value, key, obj) { + (predicate(value, key, obj) ? pass : fail).push(value); + }); + return [pass, fail]; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[0]; + if (n < 0) return []; + return slice.call(array, 0, n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[array.length - 1]; + return slice.call(array, Math.max(array.length - n, 0)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, n == null || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, strict, output) { + if (shallow && _.every(input, _.isArray)) { + return concat.apply(output, input); + } + for (var i = 0, length = input.length; i < length; i++) { + var value = input[i]; + if (!_.isArray(value) && !_.isArguments(value)) { + if (!strict) output.push(value); + } else if (shallow) { + push.apply(output, value); + } else { + flatten(value, shallow, strict, output); + } + } + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, false, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iteratee, context) { + if (array == null) return []; + if (!_.isBoolean(isSorted)) { + context = iteratee; + iteratee = isSorted; + isSorted = false; + } + if (iteratee != null) iteratee = _.iteratee(iteratee, context); + var result = []; + var seen = []; + for (var i = 0, length = array.length; i < length; i++) { + var value = array[i]; + if (isSorted) { + if (!i || seen !== value) result.push(value); + seen = value; + } else if (iteratee) { + var computed = iteratee(value, i, array); + if (_.indexOf(seen, computed) < 0) { + seen.push(computed); + result.push(value); + } + } else if (_.indexOf(result, value) < 0) { + result.push(value); + } + } + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(flatten(arguments, true, true, [])); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + if (array == null) return []; + var result = []; + var argsLength = arguments.length; + for (var i = 0, length = array.length; i < length; i++) { + var item = array[i]; + if (_.contains(result, item)) continue; + for (var j = 1; j < argsLength; j++) { + if (!_.contains(arguments[j], item)) break; + } + if (j === argsLength) result.push(item); + } + return result; + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = flatten(slice.call(arguments, 1), true, true, []); + return _.filter(array, function(value){ + return !_.contains(rest, value); + }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function(array) { + if (array == null) return []; + var length = _.max(arguments, 'length').length; + var results = Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(arguments, i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, length = list.length; i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // Return the position of the first occurrence of an item in an array, + // or -1 if the item is not included in the array. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, length = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted; + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + for (; i < length; i++) if (array[i] === item) return i; + return -1; + }; + + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var idx = array.length; + if (typeof from == 'number') { + idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1); + } + while (--idx >= 0) if (array[idx] === item) return idx; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = step || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var range = Array(length); + + for (var idx = 0; idx < length; idx++, start += step) { + range[idx] = start; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var Ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + var args, bound; + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); + args = slice.call(arguments, 2); + bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + Ctor.prototype = func.prototype; + var self = new Ctor; + Ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (_.isObject(result)) return result; + return self; + }; + return bound; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + return function() { + var position = 0; + var args = boundArgs.slice(); + for (var i = 0, length = args.length; i < length; i++) { + if (args[i] === _) args[i] = arguments[position++]; + } + while (position < arguments.length) args.push(arguments[position++]); + return func.apply(this, args); + }; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var i, length = arguments.length, key; + if (length <= 1) throw new Error('bindAll must be passed function names'); + for (i = 1; i < length; i++) { + key = arguments[i]; + obj[key] = _.bind(obj[key], obj); + } + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memoize = function(key) { + var cache = memoize.cache; + var address = hasher ? hasher.apply(this, arguments) : key; + if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); + return cache[address]; + }; + memoize.cache = {}; + return memoize; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ + return func.apply(null, args); + }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + if (!options) options = {}; + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + if (!timeout) context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0 || remaining > wait) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + if (!timeout) context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + + if (last < wait && last > 0) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + if (!timeout) context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a negated version of the passed-in predicate. + _.negate = function(predicate) { + return function() { + return !predicate.apply(this, arguments); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var args = arguments; + var start = args.length - 1; + return function() { + var i = start; + var result = args[start].apply(this, arguments); + while (i--) result = args[i].call(this, result); + return result; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Returns a function that will only be executed before being called N times. + _.before = function(times, func) { + var memo; + return function() { + if (--times > 0) { + memo = func.apply(this, arguments); + } else { + func = null; + } + return memo; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = _.partial(_.before, 2); + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + if (!_.isObject(obj)) return obj; + var source, prop; + for (var i = 1, length = arguments.length; i < length; i++) { + source = arguments[i]; + for (prop in source) { + if (hasOwnProperty.call(source, prop)) { + obj[prop] = source[prop]; + } + } + } + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj, iteratee, context) { + var result = {}, key; + if (obj == null) return result; + if (_.isFunction(iteratee)) { + iteratee = createCallback(iteratee, context); + for (key in obj) { + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; + } + } else { + var keys = concat.apply([], slice.call(arguments, 1)); + obj = new Object(obj); + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (key in obj) result[key] = obj[key]; + } + } + return result; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj, iteratee, context) { + if (_.isFunction(iteratee)) { + iteratee = _.negate(iteratee); + } else { + var keys = _.map(concat.apply([], slice.call(arguments, 1)), String); + iteratee = function(value, key) { + return !_.contains(keys, key); + }; + } + return _.pick(obj, iteratee, context); + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + if (!_.isObject(obj)) return obj; + for (var i = 1, length = arguments.length; i < length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a === 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className !== toString.call(b)) return false; + switch (className) { + // Strings, numbers, regular expressions, dates, and booleans are compared by value. + case '[object RegExp]': + // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return '' + a === '' + b; + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. + // Object(NaN) is equivalent to NaN + if (+a !== +a) return +b !== +b; + // An `egal` comparison is performed for other numeric values. + return +a === 0 ? 1 / +a === 1 / b : +a === +b; + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a === +b; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] === a) return bStack[length] === b; + } + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if ( + aCtor !== bCtor && + // Handle Object.create(x) cases + 'constructor' in a && 'constructor' in b && + !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + ) { + return false; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size, result; + // Recursively compare objects and arrays. + if (className === '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size === b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Deep compare objects. + var keys = _.keys(a), key; + size = keys.length; + // Ensure that both objects contain the same number of properties before comparing deep equality. + result = _.keys(b).length === size; + if (result) { + while (size--) { + // Deep compare each member + key = keys[size]; + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) === '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) === '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return _.has(obj, 'callee'); + }; + } + + // Optimize `isFunction` if appropriate. Work around an IE 11 bug. + if (typeof /./ !== 'function') { + _.isFunction = function(obj) { + return typeof obj == 'function' || false; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj !== +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return obj != null && hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iteratees. + _.identity = function(value) { + return value; + }; + + // Predicate-generating functions. Often useful outside of Underscore. + _.constant = function(value) { + return function() { + return value; + }; + }; + + _.noop = function(){}; + + _.property = function(key) { + return function(obj) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of `key:value` pairs. + _.matches = function(attrs) { + var pairs = _.pairs(attrs), length = pairs.length; + return function(obj) { + if (obj == null) return !length; + obj = new Object(obj); + for (var i = 0; i < length; i++) { + var pair = pairs[i], key = pair[0]; + if (pair[1] !== obj[key] || !(key in obj)) return false; + } + return true; + }; + }; + + // Run a function **n** times. + _.times = function(n, iteratee, context) { + var accum = Array(Math.max(0, n)); + iteratee = createCallback(iteratee, context, 1); + for (var i = 0; i < n; i++) accum[i] = iteratee(i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { + return new Date().getTime(); + }; + + // List of HTML entities for escaping. + var escapeMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + var unescapeMap = _.invert(escapeMap); + + // Functions for escaping and unescaping strings to/from HTML interpolation. + var createEscaper = function(map) { + var escaper = function(match) { + return map[match]; + }; + // Regexes for identifying a key that needs to be escaped + var source = '(?:' + _.keys(map).join('|') + ')'; + var testRegexp = RegExp(source); + var replaceRegexp = RegExp(source, 'g'); + return function(string) { + string = string == null ? '' : '' + string; + return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; + }; + }; + _.escape = createEscaper(escapeMap); + _.unescape = createEscaper(unescapeMap); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property) { + if (object == null) return void 0; + var value = object[property]; + return _.isFunction(value) ? object[property]() : value; + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\u2028|\u2029/g; + + var escapeChar = function(match) { + return '\\' + escapes[match]; + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + // NB: `oldSettings` only exists for backwards compatibility. + _.template = function(text, settings, oldSettings) { + if (!settings && oldSettings) settings = oldSettings; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset).replace(escaper, escapeChar); + index = offset + match.length; + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } else if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } else if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + + // Adobe VMs need the match returned to produce the correct offest. + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + 'return __p;\n'; + + try { + var render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled source as a convenience for precompilation. + var argument = settings.variable || 'obj'; + template.source = 'function(' + argument + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function. Start chaining a wrapped Underscore object. + _.chain = function(obj) { + var instance = _(obj); + instance._chain = true; + return instance; + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + _.each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + _.each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + // Extracts the result from a wrapped and chained object. + _.prototype.value = function() { + return this._wrapped; + }; + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}.call(this)); diff --git a/workflow/engine/methods/setup/setupSchemas/triggerFillReportByProcess.sql b/workflow/engine/methods/setup/setupSchemas/triggerFillReportByProcess.sql new file mode 100644 index 000000000..da1aeef85 --- /dev/null +++ b/workflow/engine/methods/setup/setupSchemas/triggerFillReportByProcess.sql @@ -0,0 +1,65 @@ +SET @INIT_DATE = '{init_date}'; +SET @FINISH_DATE = '{finish_date}'; + +DELETE FROM PRO_REPORTING WHERE `YEAR` >= DATE_FORMAT(CAST(@INIT_DATE AS DATE), '%Y') +AND `MONTH` >= DATE_FORMAT(CAST(@INIT_DATE AS DATE), '%m') +AND `YEAR` <= DATE_FORMAT(CAST(@FINISH_DATE AS DATE), '%Y') +AND `MONTH` <= DATE_FORMAT(CAST(@FINISH_DATE AS DATE), '%m'); + +INSERT INTO PRO_REPORTING ( + PRO_UID, + `MONTH`, + `YEAR`, + AVG_TIME, + SDV_TIME, + TOTAL_CASES_IN, + TOTAL_CASES_OUT, + CONFIGURED_PROCESS_TIME, + CONFIGURED_PROCESS_COST, + TOTAL_CASES_OPEN, + TOTAL_CASES_OVERDUE, + TOTAL_CASES_ON_TIME +) + +SELECT + APPLICATION.PRO_UID, + DATE_FORMAT(APPLICATION.APP_INIT_DATE, '%m') AS `MONTH`, + DATE_FORMAT(APPLICATION.APP_INIT_DATE, '%Y') AS `YEAR`, + AVG(APPLICATION.APP_DURATION) AS `AVG_TIME`, + STD(APPLICATION.APP_DURATION) AS `STD_TIME`, + COUNT(APPLICATION.APP_INIT_DATE) AS `TOTAL_CASES_IN`, + COUNT(APPLICATION.APP_FINISH_DATE) AS `TOTAL_CASES_OUT`, + NULL, + NULL, + count(if(APPLICATION.APP_FINISH_DATE != null, NULL, 1)) AS TOTAL_CASES_OPEN, + count(if(APPLICATION.APP_DELAY_DURATION > 0, 1, NULL)) AS TOTAL_CASES_OVERDUE, + count(if(APPLICATION.APP_DELAY_DURATION <= 0, 1, NULL)) AS TOTAL_CASES_ON_TIME +FROM + APPLICATION FORCE INDEX (PRIMARY) +WHERE + APPLICATION.APP_INIT_DATE BETWEEN CAST(@INIT_DATE AS DATETIME) AND CAST(@FINISH_DATE AS DATETIME) +GROUP BY APPLICATION.PRO_UID; + + +UPDATE PRO_REPORTING +SET PRO_REPORTING.CONFIGURED_PROCESS_TIME = ( + SELECT SUM(if (TASK.TAS_TIMEUNIT = "DAYS", (TASK.TAS_DURATION*8), TASK.TAS_DURATION)) + FROM TASK + WHERE PRO_REPORTING.PRO_UID = TASK.PRO_UID +); + +UPDATE PRO_REPORTING +SET PRO_REPORTING.CONFIGURED_PROCESS_COST = ( + SELECT SUM(USERS.USR_COST_BY_HOUR) + FROM TASK, TASK_USER, USERS + WHERE TASK.PRO_UID = PRO_REPORTING.PRO_UID + AND TASK.TAS_UID = TASK_USER.TAS_UID + AND TASK_USER.USR_UID = USERS.USR_UID +) OR ( + SELECT SUM(USERS.USR_COST_BY_HOUR) + FROM TASK, TASK_USER, GROUP_USER, USERS + WHERE PRO_REPORTING.PRO_UID = TASK.PRO_UID + AND TASK.TAS_UID = TASK_USER.TAS_UID + AND TASK_USER.USR_UID = GROUP_USER.GRP_UID + AND GROUP_USER.USR_UID = USERS.USR_UID +) \ No newline at end of file diff --git a/workflow/engine/methods/setup/setupSchemas/triggerFillReportByUser.sql b/workflow/engine/methods/setup/setupSchemas/triggerFillReportByUser.sql new file mode 100644 index 000000000..9ffb5b5ea --- /dev/null +++ b/workflow/engine/methods/setup/setupSchemas/triggerFillReportByUser.sql @@ -0,0 +1,61 @@ +SET @INIT_DATE = '{init_date}'; +SET @FINISH_DATE = '{finish_date}'; + +DELETE FROM USR_REPORTING WHERE `YEAR` >= DATE_FORMAT(CAST(@INIT_DATE AS DATE), '%Y') +AND `MONTH` >= DATE_FORMAT(CAST(@INIT_DATE AS DATE), '%m') +AND `YEAR` <= DATE_FORMAT(CAST(@FINISH_DATE AS DATE), '%Y') +AND `MONTH` <= DATE_FORMAT(CAST(@FINISH_DATE AS DATE), '%m'); + +INSERT INTO USR_REPORTING ( + USR_UID, + TAS_UID, + PRO_UID, + MONTH, + YEAR, + TOTAL_TIME_BY_TASK, + TOTAL_CASES_IN, + TOTAL_CASES_OUT, + USER_HOUR_COST, + AVG_TIME, + SDV_TIME, + CONFIGURED_TASK_TIME, + TOTAL_CASES_OVERDUE, + TOTAL_CASES_ON_TIME +) + +SELECT + ACV.USR_UID, + ACV.TAS_UID, + ACV.PRO_UID, + DATE_FORMAT(ACV.DEL_INIT_DATE, '%m') AS `MONTH`, + DATE_FORMAT(ACV.DEL_INIT_DATE, '%Y') AS `YEAR`, + SUM(ACV.DEL_DURATION) AS TOT_TIME_BY_TASK, + COUNT(ACV.DEL_INIT_DATE) AS TOT_CASES_IN, + COUNT(ACV.DEL_FINISH_DATE) AS TOT_CASES_OUT, + NULL, + AVG(DEL_DURATION) AS `AVG_TIME`, + STD(DEL_DURATION) AS `STD_TIME`, + NULL, + count(if(ACV.DEL_DELAY_DURATION > 0, 1, NULL)) AS TOTAL_CASES_OVERDUE, + count(if(ACV.DEL_DELAY_DURATION <= 0, 1, NULL)) AS TOTAL_CASES_ON_TIME +FROM + APP_CACHE_VIEW AS ACV +WHERE + ACV.DEL_INIT_DATE BETWEEN CAST(@INIT_DATE AS DATETIME) AND CAST(@FINISH_DATE AS DATETIME) +GROUP BY ACV.USR_UID , ACV.TAS_UID , ACV.PRO_UID; + + +UPDATE USR_REPORTING +INNER JOIN +USERS +ON USR_REPORTING.USR_UID = USERS.USR_UID +SET USR_REPORTING.USER_HOUR_COST = USERS.USR_COST_BY_HOUR; + +UPDATE USR_REPORTING +INNER JOIN +TASK +ON USR_REPORTING.TAS_UID = TASK.TAS_UID +SET USR_REPORTING.CONFIGURED_TASK_TIME = if (TASK.TAS_TIMEUNIT = "DAYS", (TASK.TAS_DURATION*8), TASK.TAS_DURATION) + + + diff --git a/workflow/engine/methods/strategicDashboard/main.php b/workflow/engine/methods/strategicDashboard/main.php new file mode 100644 index 000000000..a5053057a --- /dev/null +++ b/workflow/engine/methods/strategicDashboard/main.php @@ -0,0 +1,34 @@ +. + * + * For more information, contact Colosa Inc, 2566 Le Jeune Rd., + * Coral Gables, FL, 33134, USA, or email info@colosa.com. + */ + +$RBAC->requirePermissions( 'PM_DASHBOARD' ); + +$G_MAIN_MENU = 'processmaker'; +$G_ID_MENU_SELECTED = 'DASHBOARD+'; + +$G_PUBLISH = new Publisher(); +$G_PUBLISH->AddContent( 'view', 'strategicDashboard/load' ); +G::RenderPage( 'publish' ); + + diff --git a/workflow/engine/methods/users/usersAjax.php b/workflow/engine/methods/users/usersAjax.php index e5be876a3..bd816cc5f 100755 --- a/workflow/engine/methods/users/usersAjax.php +++ b/workflow/engine/methods/users/usersAjax.php @@ -1,13 +1,4 @@ xssFilterHard($_POST); -if(isset($_SESSION['USER_LOGGED'])) { - $_SESSION['USER_LOGGED'] = $filter->xssFilterHard($_SESSION['USER_LOGGED']); -} -if(isset($_SESSION['USR_USERNAME'])) { -$_SESSION['USR_USERNAME'] = $filter->xssFilterHard($_SESSION['USR_USERNAME']); -} global $RBAC; $result = new StdClass(); @@ -164,6 +155,10 @@ switch ($_POST['action']) { $zipCode = $form['USR_ZIP_CODE'] ? " - Zip Code: ". $form['USR_ZIP_CODE'] : ""; $position = $form['USR_POSITION'] ? " - Position: ". $form['USR_POSITION'] : ""; $role = $form['USR_ROLE'] ? " - Role: ". $form['USR_ROLE'] : ""; + /*----------------------------------********---------------------------------*/ + $costByHour = $form['USR_COST_BY_HOUR'] ? $form['USR_COST_BY_HOUR'] : ""; + $unit = $form['USR_UNIT_COST'] ? $form['USR_UNIT_COST'] : ""; + /*----------------------------------********---------------------------------*/ if ($form['USR_UID'] == '') { $criteria = new Criteria(); @@ -182,6 +177,7 @@ switch ($_POST['action']) { $aData['USR_UPDATE_DATE'] = date('Y-m-d H:i:s'); $aData['USR_BIRTHDAY'] = date('Y-m-d'); $aData['USR_AUTH_USER_DN'] = $form['USR_AUTH_USER_DN']; + //fixing bug in inactive user when the admin create a new user. $statusWF = $form['USR_STATUS']; $aData['USR_STATUS'] = $form['USR_STATUS'] ;//== 'ACTIVE' ? 1 : 0; @@ -202,6 +198,10 @@ switch ($_POST['action']) { $aData['USR_POSITION'] = $form['USR_POSITION']; // $aData['USR_RESUME'] = $form['USR_RESUME']; $aData['USR_ROLE'] = $form['USR_ROLE']; + /*----------------------------------********---------------------------------*/ + $aData['USR_COST_BY_HOUR'] = $form['USR_COST_BY_HOUR']; + $aData['USR_UNIT_COST'] = $form['USR_UNIT_COST']; + /*----------------------------------********---------------------------------*/ $aData['USR_REPLACED_BY'] = $form['USR_REPLACED_BY']; require_once 'classes/model/Users.php'; @@ -373,7 +373,14 @@ switch ($_POST['action']) { if (isset($form['USR_ROLE'])) { $aData['USR_ROLE'] = $form['USR_ROLE']; } - + /*----------------------------------********---------------------------------*/ + if (isset($form['USR_COST_BY_HOUR'])) { + $aData['USR_COST_BY_HOUR'] = $form['USR_COST_BY_HOUR']; + } + if (isset($form['USR_UNIT_COST'])) { + $aData['USR_UNIT_COST'] = $form['USR_UNIT_COST']; + } + /*----------------------------------********---------------------------------*/ if (isset($form['USR_REPLACED_BY'])) { $aData['USR_REPLACED_BY'] = $form['USR_REPLACED_BY']; } diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Catalog.php b/workflow/engine/src/ProcessMaker/BusinessModel/Catalog.php new file mode 100644 index 000000000..bdb01c969 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Catalog.php @@ -0,0 +1,80 @@ + + * @copyright Colosa - Bolivia + */ +class Catalog +{ + + /** + * Get CatalogUid by UserUid + * + * @param string $cat_type type of catalog + * + * return uid + * + * @author Marco Antonio Nina + **/ + public function getCatalogByType($cat_type) + { + $catalog = new \Catalog(); + $response = $catalog->loadByType($cat_type); + return $response; + } + + /** + * Create Catalog + * + * @param array $arrayData Data + * + * return array Return data of the new Group created + * + * @author Marco Antonio Nina + */ + public function create($arrayData) + { + $catalog = new \Catalog(); + $response = $catalog->create($arrayData); + return $response; + } + + /** + * Update Catalog + * + * @param string $cat_uid Unique id of Group + * @param string $cat_type Unique id of Group + * @param array $arrayData Data + * + * return array Return data of the new Group update + * + * @author Marco Antonio Nina + */ + public function update($cat_uid, $cat_type, $arrayData) + { + $catalog = new \Catalog(); + $response = $catalog->update($cat_uid, $cat_type, $arrayData); + return $response; + } + + /** + * Delete Catalog + * + * @param string $cat_uid Unique id of Group + * @param string $cat_type Unique id of Group + * + * return void + * + * @author Marco Antonio Nina + */ + public function delete($cat_uid, $cat_type) + { + $catalog = new \Catalog(); + $response = $catalog->delete($cat_uid, $cat_type); + return $response; + } +} + diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Dashboard.php b/workflow/engine/src/ProcessMaker/BusinessModel/Dashboard.php new file mode 100644 index 000000000..318f32c5e --- /dev/null +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Dashboard.php @@ -0,0 +1,461 @@ + + * @copyright Colosa - Bolivia + */ +class Dashboard { + + /** + * Get DashboardUid by UserUid + * + * @param string $usr_uid Unique id of User + * + * return uid + * + * @author Jenny Murillo + */ + public function getDashboardsUidByUser($usr_uid) + { + require_once (PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "DashboardDasInd.php"); + $oDashboardDasInd = new \DashboardDasInd(); + + $response = $oDashboardDasInd->loadByOwner($usr_uid); + return $response; + } + + /** + * Get Dashboard Data by UserUid + * + * @param string $usr_uid Unique id of User + * + * return uid + * + * @author Jenny Murillo + */ + public function getDashboardDataByUser($usr_uid) + { + $resp = array(); + $dashboards = $this->getDashboardsUidByUser($usr_uid); + $existFavorite = false; + foreach($dashboards as $i=>$x) { + $resp[$i] = $this->getDashboard($x['DAS_UID']); + $Dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $dashConfig = $Dashboard->getConfig($usr_uid); + $resp[$i]['DAS_FAVORITE'] = 0; + foreach ($dashConfig as $dashId=>$dashData) { + if($dashId == $x['DAS_UID'] ) { + $resp[$i]['DAS_FAVORITE'] = $dashData['dashFavorite']; + if ($dashData['dashFavorite']==1) { + $existFavorite = true; + } + } + } + } + + //if no favorite is set, the default vavorite is the first one + if ($existFavorite == false && $dashboards != null && sizeof($dashboards)>0) { + $resp[0]['DAS_FAVORITE'] = 1; + } + return $resp; + } + + /** + * Get Users of a dashboard + * + * @param string $das_uid Unique id of the Dashboard + * + * return uid + * + * @author Jenny Murillo + */ + public function getUsersOfDashboard($das_uid) + { + require_once (PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "DashboardDasInd.php"); + $oDashboardDasInd = new \DashboardDasInd(); + + $response = $oDashboardDasInd->loadByDashboards($das_uid); + return $response; + } + + /** + * Get dashboard data + * + * @param string $das_uid Unique id of the Dashboard + * + * return uid + * + * @author Jenny Murillo + */ + public function getDashboard($das_uid) + { + $oDashboard = new \Dashboard(); + $response = $oDashboard->load($das_uid); + return $response; + } + + /** + * Get dashboard indicators + * + * @param string $dasInd_uid Unique id of the Dashboard indicator + * + * return id + * + * @author Jenny Murillo + */ + public function getIndicator($dasInd_uid) + { + require_once (PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "DashboardIndicator.php"); + $oDashboardIndicator = new \DashboardIndicator(); + + $response = $oDashboardIndicator->load($dasInd_uid); + return $response; + } + + + /** + * Get dashboard indicators by das_uid + * + * @param string $das_uid Unique id of the Dashboard + * @param string $dateIni + * @param string $dateFin + * @param string $usrUid + * + * return uid + * + * @author Jenny Murillo + */ + public function getIndicatorsByDasUid($das_uid, $dateIni, $dateFin, $usrUid) + { + $oDashboardIndicator = new \DashboardIndicator(); + + $response = $oDashboardIndicator->loadbyDasUid($das_uid, $dateIni, $dateFin, $usrUid); + return $response; + } + + /** + * Get list All dashboards + * + * @access public + * @param array $options, Data for list + * @return array + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + */ + public function getListDashboards($options = array()) + { + Validator::isArray($options, '$options'); + + G::LoadClass("dashboards"); + $dir = isset( $options["dir"] ) ? $options["dir"] : "DESC"; + $sort = isset( $options["sort"] ) ? $options["sort"] : "DASHBOARD.DAS_TITLE"; + $start = isset( $options["start"] ) ? $options["start"] : "0"; + $limit = isset( $options["limit"] ) ? $options["limit"] : ""; + $search = isset( $options["search"] ) ? $options["search"] : ""; + $paged = isset( $options["paged"] ) ? $options["paged"] : true; + $type = "extjs"; + + $start = (int)$start; + $start = abs($start); + if ($start != 0) { + $start--; + } + $limit = (int)$limit; + $limit = abs($limit); + if ($limit == 0) { + G::LoadClass("configuration"); + $conf = new \Configurations(); + $configList = $conf->getConfiguration('ENVIRONMENT_SETTINGS', ''); + if (isset($configList['casesListRowNumber'])) { + $limit = (int)$configList['casesListRowNumber']; + } else { + $limit = 25; + } + } else { + $limit = (int)$limit; + } + + if ($sort != 'DASHBOARD.DAS_TITLE') { + $sort = G::toUpper($sort); + $columnsAppCacheView = DashboardPeer::getFieldNames(\BasePeer::TYPE_FIELDNAME); + if (!(in_array($sort, $columnsAppCacheView))) { + $sort = 'APP_CACHE_VIEW.APP_NUMBER'; + } + } + $dir = G::toUpper($dir); + if (!($dir == 'DESC' || $dir == 'ASC')) { + $dir = 'DESC'; + } + + $dashboards = new \Dashboards(); + $result = $dashboards->getListDashboards($start, $limit, $sort, $dir, $search); + + if ($paged == false) { + $response = $result['data']; + } else { + $response['total'] = $result['totalCount']; + $response['start'] = $start+1; + $response['limit'] = $limit; + $response['sort'] = G::toLower($sort); + $response['dir'] = G::toLower($dir); + $response['search'] = $search; + + $response['data'] = $result['data']; + } + return $response; + } + + /** + * Get list All owners of dashboards + * + * @access public + * @param array $options, Data for list + * @return array + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + */ + public function getOwnerByDasUid($options = array()) + { + Validator::isArray($options, '$options'); + + G::LoadClass("dashboards"); + $das_uid = isset( $options["das_uid"] ) ? $options["das_uid"] : ""; + $start = isset( $options["start"] ) ? $options["start"] : "0"; + $limit = isset( $options["limit"] ) ? $options["limit"] : ""; + $search = isset( $options["search"] ) ? $options["search"] : ""; + $paged = isset( $options["paged"] ) ? $options["paged"] : true; + $type = "extjs"; + + $start = (int)$start; + $start = abs($start); + if ($start != 0) { + $start--; + } + $limit = (int)$limit; + $limit = abs($limit); + if ($limit == 0) { + G::LoadClass("configuration"); + $conf = new \Configurations(); + $configList = $conf->getConfiguration('ENVIRONMENT_SETTINGS', ''); + if (isset($configList['casesListRowNumber'])) { + $limit = (int)$configList['casesListRowNumber']; + } else { + $limit = 25; + } + } else { + $limit = (int)$limit; + } + + $dashboards = new \Dashboards(); + $result = $dashboards->getOwnerByDasUid($das_uid, $start, $limit, $search); + + + if ($paged == false) { + $response = $result['data']; + } else { + $response['totalCount'] = $result['totalCount']; + $response['start'] = $start+1; + $response['limit'] = $limit; + $response['search'] = $search; + + $response['owner'] = $result['data']; + } + return $response; + } + + /** + * Create Dashboard + * + * @param array $arrayData Data + * + * return id new Dashboard created + * + * @author Marco Antonio Nina + */ + public function createDashboard($arrayData) + { + $dashboard = new \Dashboard(); + $response = $dashboard->createOrUpdate($arrayData); + return $response; + } + + /** + * Delete Dashboard + * + * @param string $das_uid Unique id + * + * return void + * + * @author Marco Antonio Nina + */ + public function deletedashboard($das_uid) + { + $dashboard = new \Dashboard(); + $response = $dashboard->remove($das_uid); + return $response; + } + + /** + * Create Dashboard Owner + * + * @param array $arrayData Data + * + * return id new Owner created + * + * @author Marco Antonio Nina + */ + public function createOwner($arrayData) + { + $dashboard = new \DashboardDasInd(); + $response = $dashboard->create($arrayData); + return $response; + } + + /** + * Delete Dashboard owner + * + * @param string $das_uid + * @param string $owner_uid + * + * return void + * + * @author Marco Antonio Nina + */ + public function deleteDashboardOwner($das_uid, $owner_uid) + { + $dashboard = new \DashboardDasInd(); + $response = $dashboard->remove($das_uid, $owner_uid); + return $response; + } + + /** + * Create Dashboard Indicator + * + * @param array $arrayData Data + * + * return id new Indicator created + * + * @author Marco Antonio Nina + */ + public function createIndicator($arrayData) + { + $dashboard = new \DashboardIndicator(); + $response = $dashboard->createOrUpdate($arrayData); + return $response; + } + + /** + * Delete Indicator + * + * @param string $das_ind_uid Unique id + * + * return void + * + * @author Marco Antonio Nina + */ + public function delete($das_ind_uid) + { + $dashboard = new \DashboardIndicator(); + $response = $dashboard->remove($das_ind_uid); + return $response; + } + + /** + * Post Dashboards User Configuration + * + * @param array $arrayData Data + * @param string $usrUid + * + * return array Return data of the user configuration + * + * @author Jenny Murillo + */ + public function postConfigByUsr($arrayData, $usrUid) + { + $cnfgData[$arrayData['dashId']] = $arrayData; + + $data['CFG_UID'] = 'DASHBOARDS_SETTINGS'; + $data['OBJ_UID'] = ''; + $data['CFG_VALUE'] = serialize($cnfgData); + $data['USR_UID'] = $usrUid; + $data['PRO_UID'] = ""; + $data['APP_UID'] = ""; + + //require_once (PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Configuration.php"); + $oConfig = new \Configuration(); + + $response = $oConfig->create($data); + return $response; + } + + /** + * Get Dashboard configuration by UserUid + * + * @param string $usr_uid Unique id of User + * + * return array + * + * @author Jenny Murillo + */ + public function getConfig($usr_uid) + { + //require_once (PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Configuration.php"); + $oConfig = new \Configuration(); + + $response = array(); + if($oConfig->exists('DASHBOARDS_SETTINGS', '', '', $usr_uid, '') == true){ + $data = $oConfig->load('DASHBOARDS_SETTINGS', '', '', $usr_uid, ''); + $response = unserialize($data['CFG_VALUE']); + } + + return $response; + } + + /** + * Put Dashboard configuration by UserUid + * + * @param array $arrayData Data + * @param string $usrUid + * + * return array + * + * @author Jenny Murillo + */ + public function putConfigByUsr($arrayData, $usrUid) + { + $oConfig = new \Configuration(); + + $cnfgData = array(); + if($oConfig->exists('DASHBOARDS_SETTINGS', '', '', $usrUid, '') == true){ + $data = $oConfig->load('DASHBOARDS_SETTINGS', '', '', $usrUid, ''); + $cnfgData = unserialize($data['CFG_VALUE']); + } + + if($arrayData['dashData']==""){ + foreach($cnfgData as $dashId=>$dashData) { + $cnfgData[$dashData['dashId']]['dashFavorite'] = 0; + } + $cnfgData[$arrayData['dashId']]['dashId'] = $arrayData['dashId']; + $cnfgData[$arrayData['dashId']]['dashFavorite'] = $arrayData['dashFavorite']; + $cnfgData[$arrayData['dashId']]['dashData'] = $arrayData['dashData']; + } else{ + $cnfgData[$arrayData['dashId']] = $arrayData; + } + + $data['CFG_UID'] = 'DASHBOARDS_SETTINGS'; + $data['OBJ_UID'] = ''; + $data['CFG_VALUE'] = serialize($cnfgData); + $data['USR_UID'] = $usrUid; + $data['PRO_UID'] = ""; + $data['APP_UID'] = ""; + + $response = $oConfig->update($data); + return $response; + } +} + diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/ReportingIndicators.php b/workflow/engine/src/ProcessMaker/BusinessModel/ReportingIndicators.php new file mode 100644 index 000000000..37bd2b45b --- /dev/null +++ b/workflow/engine/src/ProcessMaker/BusinessModel/ReportingIndicators.php @@ -0,0 +1,300 @@ +peiProcesses($indicatorUid, $measureDate, $measureDate, $language); + $arr = $calculator->indicatorData($indicatorUid); + $indicator = $arr[0]; + $processesId = $indicator['DAS_UID_PROCESS']; + $peiValue = current(reset($calculator-> peiHistoric($processesId, $measureDate, $measureDate, \ReportingPeriodicityEnum::NONE))); + $peiCost = current(reset($calculator->peiCostHistoric($processesId, $measureDate, $measureDate, \ReportingPeriodicityEnum::NONE))); + $peiCompare = current(reset($calculator->peiHistoric($processesId, $compareDate, $compareDate, \ReportingPeriodicityEnum::NONE))); + + $retval = array("efficiencyIndex" => $peiValue, + "efficiencyVariation" => ($peiValue-$peiCompare), + "inefficiencyCost" => $peiCost, + "data"=>$processes); + return $retval; + } + + /** + * Lists tasks of a employee and it's statistics (efficiency, average times, etc.) + * + * @param array $employeeList array with the list of employeees to filter the results. + * @param DateTime $initDate date from the index will be calculated + * @param DateTime $endDate date until the index will be calculated + * @param string $language language for the names (en, es, etc.) + * + * return decimal value + */ + public function getUeiCompleteData($indicatorUid, $measureDate, $compareDate, $language) + { + G::loadClass('indicatorsCalculator'); + $calculator = new \IndicatorsCalculator(); + $groups = $calculator->ueiUserGroups($indicatorUid, $measureDate, $measureDate, $language); + + $groupIds = array(); + foreach($groups as $p) { + array_push($groupIds, $p['uid']); + } + + if (sizeof($groupIds) == 0) { + $groupIds = null; + } + + //TODO think what if each indicators has a group or user subset assigned. Now are all + $ueiValue = current(reset($calculator->ueiHistoric(null, $measureDate, $measureDate, \ReportingPeriodicityEnum::NONE))); + $arrCost = $calculator->ueiUserGroups($indicatorUid, $measureDate, $measureDate, $language); + + $ueiCost = (sizeof($arrCost) > 0) + ? $arrCost[0]['inefficiencyCost'] + : null; + + $ueiCompare = current(reset($calculator->ueiHistoric(null, $compareDate, $compareDate, \ReportingPeriodicityEnum::NONE))); + + $retval = array("efficiencyIndex" => $ueiValue, + "efficiencyVariation" => ($ueiValue-$ueiCompare), + "inefficiencyCost" => $ueiCost, + "data"=>$groups); + return $retval; + } + + /** + * Lists tasks of a employee and it's statistics (efficiency, average times, etc.) + * + * @param array $employeeList array with the list of employeees to filter the results. + * @param DateTime $initDate date from the index will be calculated + * @param DateTime $endDate date until the index will be calculated + * @param string $language language for the names (en, es, etc.) + * + * return decimal value + */ + public function getUeiGroupsStatistics($groupId, $initDate, $endDate, $language) + { + G::loadClass('indicatorsCalculator'); + $calculator = new \IndicatorsCalculator(); + $retval = $calculator->groupEmployeesData($groupId, $initDate, $endDate, $language); + return $retval; + } + + /** + * Lists tasks of a process and it's statistics (efficiency, average times, etc.) + * + * @param array $processList array with the list of processes to filter the results. + * @param DateTime $initDate date from the index will be calculated + * @param DateTime $endDate date until the index will be calculated + * @param string $language language for the names (en, es, etc.) + * + * return decimal value + */ + public function getPeiTasksStatistics($processList, $initDate, $endDate, $language) + { + G::loadClass('indicatorsCalculator'); + $calculator = new \IndicatorsCalculator(); + $retval = $calculator->peiTasks($processList, $initDate, $endDate, $language); + return $retval; + } + +// /** +// * Lists tasks of a employee and it's statistics (efficiency, average times, etc.) +// * +// * @param array $employeeList array with the list of employeees to filter the results. +// * @param DateTime $initDate date from the index will be calculated +// * @param DateTime $endDate date until the index will be calculated +// * +// * return decimal value +// */ +// public function getEmployeeTasksInfoList($employeeList, $initDate, $endDate, $language) +// { +// G::loadClass('IndicatorsCalculator'); +// $calculator = new \IndicatorsCalculator(); +// $retval = $calculator->employeeTasksInfoList($employeeList, $initDate, $endDate, $language); +// return $retval; +// } +// +// /** +// * Returns the percent of Cases with Overdue time +// * +// * @param array $processList array with the list of processes to filter the results. +// * @param DateTime $initDate date from the index will be calculated +// * @param DateTime $endDate date until the index will be calculated +// * +// * return decimal value +// */ +// public function getPercentOverdueCasesByProcess($processList, $initDate, $endDate) +// { +// G::loadClass('IndicatorsCalculator'); +// $calculator = new \IndicatorsCalculator(); +// $retval = $calculator->percentOverdueCasesByProcess($processList, $initDate, $endDate); +// return $retval; +// } +// +// /** +// * Returns the percent of Cases with Overdue by period (month, semester, etc.) +// * +// * @param array $processList array with the list of processes to filter the results. +// * @param DateTime $initDate date from the index will be calculated +// * @param DateTime $endDate date until the index will be calculated +// * +// * return decimal value +// */ +// public function getPercentOverdueCasesByProcessHistory($processList, $initDate, $endDate, $periodicity) +// { +// G::loadClass('IndicatorsCalculator'); +// $calculator = new \IndicatorsCalculator(); +// $retval = $calculator->percentOverdueCasesByProcessList($processList, $initDate, $endDate, \ReportingPeriodicityEnum::fromValue($periodicity)); +// return $retval; +// } +// +// /** +// * Returns the number of new Cases +// * +// * @param array $processList array with the list of processes to filter the results. +// * @param DateTime $initDate date from the index will be calculated +// * @param DateTime $endDate date until the index will be calculated +// * +// * return decimal value +// */ +// public function getPercentNewCasesByProcess($processList, $initDate, $endDate) +// { +// G::loadClass('IndicatorsCalculator'); +// $calculator = new \IndicatorsCalculator(); +// $retval = $calculator->totalNewCasesByProcess($processList, $initDate, $endDate); +// return $retval; +// } +// +// /** +// * Returns the total of new Cases historically +// * +// * @param array $processList array with the list of processes to filter the results. +// * @param DateTime $initDate date from the index will be calculated +// * @param DateTime $endDate date until the index will be calculated +// * +// * return decimal value +// */ +// public function getPercentNewCasesByProcessHistory($processList, $initDate, $endDate, $periodicity) +// { +// G::loadClass('IndicatorsCalculator'); +// $calculator = new \IndicatorsCalculator(); +// $retval = $calculator->totalNewCasesByProcessList($processList, $initDate, $endDate, \ReportingPeriodicityEnum::fromValue($periodicity)); +// return $retval; +// } +// +// +// +// +// /** +// * Returns the number of completed Cases +// * +// * @param array $processList array with the list of processes to filter the results. +// * @param DateTime $initDate date from the index will be calculated +// * @param DateTime $endDate date until the index will be calculated +// * +// * return decimal value +// */ +// public function getPercentCompletedCasesByProcess($processList, $initDate, $endDate) +// { +// G::loadClass('IndicatorsCalculator'); +// $calculator = new \IndicatorsCalculator(); +// $retval = $calculator->totalCompletedCasesByProcess($processList, $initDate, $endDate); +// return $retval; +// } +// +// /** +// * Returns the total of completed Cases historically +// * +// * @param array $processList array with the list of processes to filter the results. +// * @param DateTime $initDate date from the index will be calculated +// * @param DateTime $endDate date until the index will be calculated +// * +// * return decimal value +// */ +// public function getPercentCompletedCasesByProcessHistory($processList, $initDate, $endDate, $periodicity) +// { +// G::loadClass('IndicatorsCalculator'); +// $calculator = new \IndicatorsCalculator(); +// $retval = $calculator->totalCompletedCasesByProcessList($processList, $initDate, $endDate, \ReportingPeriodicityEnum::fromValue($periodicity)); +// return $retval; +// } + +// /** +// * +// * +// * @param array $processList array with the list of processes to filter the results. +// * @param DateTime $initDate date from the index will be calculated +// * @param DateTime $endDate date until the index will be calculated +// * +// * return decimal value +// */ +// public function getProcessEfficiencyIndexData($processId, $initDate, $endDate) +// { +// G::loadClass('IndicatorsCalculator'); +// $calculator = new \IndicatorsCalculator(); +// $indexValue = $calculator->processEfficiencyIndex ($processId, $initDate, $endDate); +// $costValue = $calculator->processEfficiencyCost ($processId, $initDate, $endDate); +// $retval = $calculator->totalCompletedCasesByProcessList($processId, $initDate, $endDate); +// return $retval; +// } + /** + * Lists tasks of a process and it's statistics (efficiency, average times, etc.) + * + * @param $indicatorId + * @param DateTime $initDate date from the index will be calculated + * @param DateTime $endDate date until the index will be calculated + * @param string $language language for the names (en, es, etc.) + * + * return decimal value + * @return array + */ + public function getGeneralIndicatorStatistics($indicatorId, $initDate, $endDate, $periodicity) + { + G::loadClass('indicatorsCalculator'); + $calculator = new \IndicatorsCalculator(); + $arr = $calculator->generalIndicatorData($indicatorId, $initDate, $endDate, \ReportingPeriodicityEnum::NONE); + $value = $arr[0]['value']; + $dataList1 = $calculator-> + generalIndicatorData($indicatorId, + $initDate, $endDate, + \ReportingPeriodicityEnum::fromValue($arr[0]['frequency1Type'])); + + $dataList2 = $calculator-> + generalIndicatorData($indicatorId, + $initDate, $endDate, + \ReportingPeriodicityEnum::fromValue($arr[0]['frequency2Type'])); + + $returnValue = array("index" => $value, + "graph1XLabel"=>$arr[0]['graph1XLabel'], + "graph1YLabel"=>$arr[0]['graph1YLabel'], + "graph2XLabel"=>$arr[0]['graph2XLabel'], + "graph2YLabel"=>$arr[0]['graph2YLabel'], + "graph1Type"=>$arr[0]['graph1Type'], + "graph2Type"=>$arr[0]['graph2Type'], + "frequency1Type"=>$arr[0]['frequency1Type'], + "frequency2Type"=>$arr[0]['frequency2Type'], + "graph1Data"=>$dataList1, + "graph2Data"=>$dataList2 + ); + return $returnValue; + } +} + diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/User.php b/workflow/engine/src/ProcessMaker/BusinessModel/User.php index b48fa5ff7..d97b9d721 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/User.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/User.php @@ -4,744 +4,6 @@ use \G; class User { - //--- --- - private $arrayFieldDefinition = array( - "USR_UID" => array("type" => "string", "required" => false, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrUid"), - "USR_FIRSTNAME" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrFirstname"), - "USR_LASTNAME" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrLastname"), - "USR_USERNAME" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrUsername"), - "USR_EMAIL" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrEmail"), - "USR_ADDRESS" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrAddress"), - "USR_ZIP_CODE" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrZipCode"), - "USR_COUNTRY" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrCountry"), - "USR_CITY" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrCity"), - "USR_LOCATION" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrLocation"), - "USR_PHONE" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrPhone"), - "USR_POSITION" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrPosition"), - "USR_REPLACED_BY" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrReplacedBy"), - "USR_DUE_DATE" => array("type" => "date", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrDueDate"), - "USR_CALENDAR" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrCalendar"), - "USR_STATUS" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array("ACTIVE", "INACTIVE", "VACATION"), "fieldNameAux" => "usrStatus"), - "USR_ROLE" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrRole"), - "USR_NEW_PASS" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrNewPass"), - "USR_CNF_PASS" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "usrCnfPass"), - "USR_UX" => array("type" => "string", "required" => false, "empty" => false, "defaultValues" => array("NORMAL", "SIMPLIFIED", "SWITCHABLE", "SINGLE"), "fieldNameAux" => "usrUx"), - "DEP_UID" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "depUid"), - "USR_BIRTHDAY" => array("type" => "date", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrBirthday"), - "USR_FAX" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrFax"), - "USR_CELLULAR" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "usrCellular"), - "USR_LOGGED_NEXT_TIME" => array("type" => "int", "required" => false, "empty" => false, "defaultValues" => array(0, 1), "fieldNameAux" => "usrLoggedNextTime") - ); - - private $formatFieldNameInUppercase = true; - - private $arrayFieldNameForException = array( - "usrPhoto" => "USR_PHOTO" - ); - - /** - * Constructor of the class - * - * return void - */ - public function __construct() - { - try { - foreach ($this->arrayFieldDefinition as $key => $value) { - $this->arrayFieldNameForException[$value["fieldNameAux"]] = $key; - } - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Set the format of the fields name (uppercase, lowercase) - * - * @param bool $flag Value that set the format - * - * return void - */ - public function setFormatFieldNameInUppercase($flag) - { - try { - $this->formatFieldNameInUppercase = $flag; - - $this->setArrayFieldNameForException($this->arrayFieldNameForException); - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Set exception users for fields - * - * @param array $arrayData Data with the fields - * - * return void - */ - public function setArrayFieldNameForException(array $arrayData) - { - try { - foreach ($arrayData as $key => $value) { - $this->arrayFieldNameForException[$key] = $this->getFieldNameByFormatFieldName($value); - } - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Get the name of the field according to the format - * - * @param string $fieldName Field name - * - * return string Return the field name according the format - */ - public function getFieldNameByFormatFieldName($fieldName) - { - try { - return ($this->formatFieldNameInUppercase)? strtoupper($fieldName) : strtolower($fieldName); - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Verify if exists the Name of a User - * - * @param string $userName Name - * @param string $userUidToExclude Unique id of User to exclude - * - * return bool Return true if exists the Name of a User, false otherwise - */ - public function existsName($userName, $userUidToExclude = "") - { - try { - $criteria = $this->getUserCriteria(); - - if ($userUidToExclude != "") { - $criteria->add(\UsersPeer::USR_UID, $userUidToExclude, \Criteria::NOT_EQUAL); - } - - $criteria->add(\UsersPeer::USR_USERNAME, $userName, \Criteria::EQUAL); - - //QUERY - $rsCriteria = \UsersPeer::doSelectRS($criteria); - - return ($rsCriteria->next())? true : false; - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Verify if exists the Name of a User - * - * @param string $userName Name - * @param string $fieldNameForException Field name for the exception - * @param string $userUidToExclude Unique id of User to exclude - * - * return void Throw exception if exists the title of a User - */ - public function throwExceptionIfExistsName($userName, $fieldNameForException, $userUidToExclude = "") - { - try { - if ($this->existsName($userName, $userUidToExclude)) { - throw new \Exception(\G::LoadTranslation("ID_USER_NAME_ALREADY_EXISTS", array($fieldNameForException, $userName))); - } - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Verify password - * - * @param string $userPassword Password - * @param string $fieldNameForException Field name for the exception - * - * return void Throw exception if password is invalid - */ - public function throwExceptionIfPasswordIsInvalid($userPassword, $fieldNameForException) - { - try { - $result = $this->testPassword($userPassword); - - if (!$result["STATUS"]) { - throw new \Exception($fieldNameForException . ": " . $result["DESCRIPTION"]); - } - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Validate the data if they are invalid (INSERT and UPDATE) - * - * @param string $userUid Unique id of User - * @param array $arrayData Data - * - * return void Throw exception if data has an invalid value - */ - public function throwExceptionIfDataIsInvalid($userUid, array $arrayData) - { - try { - //Set variables - $arrayUserData = ($userUid == "")? array() : $this->getUser($userUid, true); - $flagInsert = ($userUid == "")? true : false; - - $arrayFinalData = array_merge($arrayUserData, $arrayData); - - //Verify data - Field definition. - $process = new \ProcessMaker\BusinessModel\Process(); - - $process->throwExceptionIfDataNotMetFieldDefinition($arrayData, $this->arrayFieldDefinition, $this->arrayFieldNameForException, $flagInsert); - - //Verify data - if (isset($arrayData["USR_USERNAME"])) { - $this->throwExceptionIfExistsName($arrayData["USR_USERNAME"], $this->arrayFieldNameForException["usrUsername"], $userUid); - } - - if (isset($arrayData["USR_EMAIL"])) { - if (!filter_var($arrayData["USR_EMAIL"], FILTER_VALIDATE_EMAIL)) { - throw new \Exception($this->arrayFieldNameForException["usrEmail"] . ": " . \G::LoadTranslation("ID_INCORRECT_EMAIL")); - } - } - - if (isset($arrayData["USR_NEW_PASS"])) { - $this->throwExceptionIfPasswordIsInvalid($arrayData["USR_NEW_PASS"], $this->arrayFieldNameForException["usrNewPass"]); - - if (!isset($arrayData["USR_CNF_PASS"])) { - throw new \Exception(\G::LoadTranslation("ID_UNDEFINED_VALUE_IS_REQUIRED", array($this->arrayFieldNameForException["usrCnfPass"]))); - } - - if ($arrayData["USR_NEW_PASS"] != $arrayData["USR_CNF_PASS"]) { - throw new \Exception($this->arrayFieldNameForException["usrNewPass"] . ", " . $this->arrayFieldNameForException["usrCnfPass"] . ": " . \G::LoadTranslation("ID_NEW_PASS_SAME_OLD_PASS")); - } - } - - if (isset($arrayData["USR_REPLACED_BY"]) && $arrayData["USR_REPLACED_BY"] != "") { - $obj = \UsersPeer::retrieveByPK($arrayData["USR_REPLACED_BY"]); - - if (is_null($obj)) { - throw new \Exception(\G::LoadTranslation("ID_USER_DOES_NOT_EXIST", array($this->arrayFieldNameForException["usrReplacedBy"], $arrayData["USR_REPLACED_BY"]))); - } - } - - if (isset($arrayData["USR_DUE_DATE"])) { - $arrayUserDueDate = explode("-", $arrayData["USR_DUE_DATE"]); - - if (ctype_digit($arrayUserDueDate[0])) { - if (!checkdate($arrayUserDueDate[1], $arrayUserDueDate[2], $arrayUserDueDate[0])) { - throw new \Exception($this->arrayFieldNameForException["usrDueDate"] . ": " . \G::LoadTranslation("ID_MSG_ERROR_DUE_DATE")); - } - } else { - throw new \Exception($this->arrayFieldNameForException["usrDueDate"] . ": " . \G::LoadTranslation("ID_MSG_ERROR_DUE_DATE")); - } - } - - if (isset($arrayData["USR_ROLE"])) { - require_once (PATH_RBAC_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Roles.php"); - - $criteria = new \Criteria("rbac"); - - $criteria->add(\RolesPeer::ROL_CODE, $arrayData["USR_ROLE"]); - $rsCriteria = \RolesPeer::doSelectRS($criteria); - - if (!$rsCriteria->next()) { - throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($this->arrayFieldNameForException["usrRole"]))); - } - } - - if (isset($arrayData["USR_COUNTRY"]) && $arrayData["USR_COUNTRY"] != "") { - $obj = \IsoCountryPeer::retrieveByPK($arrayData["USR_COUNTRY"]); - - if (is_null($obj)) { - throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($this->arrayFieldNameForException["usrCountry"]))); - } - } - - if (isset($arrayData["USR_CITY"]) && $arrayData["USR_CITY"] != "") { - if (!isset($arrayFinalData["USR_COUNTRY"]) || $arrayFinalData["USR_COUNTRY"] == "") { - throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($this->arrayFieldNameForException["usrCountry"]))); - } - - $obj = \IsoSubdivisionPeer::retrieveByPK($arrayFinalData["USR_COUNTRY"], $arrayData["USR_CITY"]); - - if (is_null($obj)) { - throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($this->arrayFieldNameForException["usrCity"]))); - } - } - - if (isset($arrayData["USR_LOCATION"]) && $arrayData["USR_LOCATION"] != "") { - if (!isset($arrayFinalData["USR_COUNTRY"]) || $arrayFinalData["USR_COUNTRY"] == "") { - throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($this->arrayFieldNameForException["usrCountry"]))); - } - - $obj = \IsoLocationPeer::retrieveByPK($arrayFinalData["USR_COUNTRY"], $arrayData["USR_LOCATION"]); - - if (is_null($obj)) { - throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($this->arrayFieldNameForException["usrLocation"]))); - } - } - - if (isset($arrayData["USR_CALENDAR"]) && $arrayData["USR_CALENDAR"] != "") { - $obj = \CalendarDefinitionPeer::retrieveByPK($arrayData["USR_CALENDAR"]); - - if (is_null($obj)) { - throw new \Exception(\G::LoadTranslation("ID_CALENDAR_DOES_NOT_EXIST", array($this->arrayFieldNameForException["usrCalendar"], $arrayData["USR_CALENDAR"]))); - } - } - - if (isset($arrayData["DEP_UID"]) && $arrayData["DEP_UID"] != "") { - $department = new \Department(); - - if (!$department->existsDepartment($arrayData["DEP_UID"])) { - throw new \Exception(\G::LoadTranslation("ID_DEPARTMENT_NOT_EXIST", array($this->arrayFieldNameForException["depUid"], $arrayData["DEP_UID"]))); - } - } - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Verify if does not exist the User in table USERS - * - * @param string $userUid Unique id of Email Server - * @param string $fieldNameForException Field name for the exception - * - * return void Throw exception if does not exist the User in table USERS - */ - public function throwExceptionIfNotExistsUser($userUid, $fieldNameForException) - { - try { - $obj = \UsersPeer::retrieveByPK($userUid); - - if (is_null($obj) || $obj->getUsrUsername() == "") { - throw new \Exception(\G::LoadTranslation("ID_USER_DOES_NOT_EXIST", array($fieldNameForException, $userUid))); - } - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Get data of a from a record - * - * @param array $record Record - * - * return array Return an array with data User - */ - public function getUserDataFromRecord(array $record) - { - try { - return array( - $this->getFieldNameByFormatFieldName("USR_UID") => $record["USR_UID"], - $this->getFieldNameByFormatFieldName("USR_USERNAME") => $record["USR_USERNAME"], - $this->getFieldNameByFormatFieldName("USR_PASSWORD") => $record["USR_PASSWORD"], - $this->getFieldNameByFormatFieldName("USR_FIRSTNAME") => $record["USR_FIRSTNAME"], - $this->getFieldNameByFormatFieldName("USR_LASTNAME") => $record["USR_LASTNAME"], - $this->getFieldNameByFormatFieldName("USR_EMAIL") => $record["USR_EMAIL"], - $this->getFieldNameByFormatFieldName("USR_DUE_DATE") => $record["USR_DUE_DATE"], - $this->getFieldNameByFormatFieldName("USR_CREATE_DATE") => $record["USR_CREATE_DATE"], - $this->getFieldNameByFormatFieldName("USR_UPDATE_DATE") => $record["USR_UPDATE_DATE"], - $this->getFieldNameByFormatFieldName("USR_STATUS") => $record["USR_STATUS"], - $this->getFieldNameByFormatFieldName("USR_COUNTRY") => $record["USR_COUNTRY"], - $this->getFieldNameByFormatFieldName("USR_CITY") => $record["USR_CITY"], - $this->getFieldNameByFormatFieldName("USR_LOCATION") => $record["USR_LOCATION"], - $this->getFieldNameByFormatFieldName("USR_ADDRESS") => $record["USR_ADDRESS"], - $this->getFieldNameByFormatFieldName("USR_PHONE") => $record["USR_PHONE"], - $this->getFieldNameByFormatFieldName("USR_FAX") => $record["USR_FAX"], - $this->getFieldNameByFormatFieldName("USR_CELLULAR") => $record["USR_CELLULAR"], - $this->getFieldNameByFormatFieldName("USR_ZIP_CODE") => $record["USR_ZIP_CODE"], - $this->getFieldNameByFormatFieldName("DEP_UID") => $record["DEP_UID"], - $this->getFieldNameByFormatFieldName("USR_POSITION") => $record["USR_POSITION"], - $this->getFieldNameByFormatFieldName("USR_RESUME") => $record["USR_RESUME"], - $this->getFieldNameByFormatFieldName("USR_BIRTHDAY") => $record["USR_BIRTHDAY"], - $this->getFieldNameByFormatFieldName("USR_ROLE") => $record["USR_ROLE"], - $this->getFieldNameByFormatFieldName("USR_REPORTS_TO") => $record["USR_REPORTS_TO"], - $this->getFieldNameByFormatFieldName("USR_REPLACED_BY") => $record["USR_REPLACED_BY"], - $this->getFieldNameByFormatFieldName("USR_UX") => $record["USR_UX"], - $this->getFieldNameByFormatFieldName("USR_TOTAL_INBOX") => $record["USR_TOTAL_INBOX"], - $this->getFieldNameByFormatFieldName("USR_TOTAL_DRAFT") => $record["USR_TOTAL_DRAFT"], - $this->getFieldNameByFormatFieldName("USR_TOTAL_CANCELLED") => $record["USR_TOTAL_CANCELLED"], - $this->getFieldNameByFormatFieldName("USR_TOTAL_PARTICIPATED") => $record["USR_TOTAL_PARTICIPATED"], - $this->getFieldNameByFormatFieldName("USR_TOTAL_PAUSED") => $record["USR_TOTAL_PAUSED"], - $this->getFieldNameByFormatFieldName("USR_TOTAL_COMPLETED") => $record["USR_TOTAL_COMPLETED"], - $this->getFieldNameByFormatFieldName("USR_TOTAL_UNASSIGNED") => $record["USR_TOTAL_UNASSIGNED"] - ); - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Get criteria for User - * - * return object - */ - public function getUserCriteria() - { - try { - $criteria = new \Criteria("workflow"); - - $criteria->addSelectColumn(\UsersPeer::USR_UID); - $criteria->addSelectColumn(\UsersPeer::USR_USERNAME); - $criteria->addSelectColumn(\UsersPeer::USR_PASSWORD); - $criteria->addSelectColumn(\UsersPeer::USR_FIRSTNAME); - $criteria->addSelectColumn(\UsersPeer::USR_LASTNAME); - $criteria->addSelectColumn(\UsersPeer::USR_EMAIL); - $criteria->addSelectColumn(\UsersPeer::USR_DUE_DATE); - $criteria->addSelectColumn(\UsersPeer::USR_CREATE_DATE); - $criteria->addSelectColumn(\UsersPeer::USR_UPDATE_DATE); - $criteria->addSelectColumn(\UsersPeer::USR_STATUS); - $criteria->addSelectColumn(\UsersPeer::USR_COUNTRY); - $criteria->addSelectColumn(\UsersPeer::USR_CITY); - $criteria->addSelectColumn(\UsersPeer::USR_LOCATION); - $criteria->addSelectColumn(\UsersPeer::USR_ADDRESS); - $criteria->addSelectColumn(\UsersPeer::USR_PHONE); - $criteria->addSelectColumn(\UsersPeer::USR_FAX); - $criteria->addSelectColumn(\UsersPeer::USR_CELLULAR); - $criteria->addSelectColumn(\UsersPeer::USR_ZIP_CODE); - $criteria->addSelectColumn(\UsersPeer::DEP_UID); - $criteria->addSelectColumn(\UsersPeer::USR_POSITION); - $criteria->addSelectColumn(\UsersPeer::USR_RESUME); - $criteria->addSelectColumn(\UsersPeer::USR_BIRTHDAY); - $criteria->addSelectColumn(\UsersPeer::USR_ROLE); - $criteria->addSelectColumn(\UsersPeer::USR_REPORTS_TO); - $criteria->addSelectColumn(\UsersPeer::USR_REPLACED_BY); - $criteria->addSelectColumn(\UsersPeer::USR_UX); - $criteria->addSelectColumn(\UsersPeer::USR_TOTAL_INBOX); - $criteria->addSelectColumn(\UsersPeer::USR_TOTAL_DRAFT); - $criteria->addSelectColumn(\UsersPeer::USR_TOTAL_CANCELLED); - $criteria->addSelectColumn(\UsersPeer::USR_TOTAL_PARTICIPATED); - $criteria->addSelectColumn(\UsersPeer::USR_TOTAL_PAUSED); - $criteria->addSelectColumn(\UsersPeer::USR_TOTAL_COMPLETED); - $criteria->addSelectColumn(\UsersPeer::USR_TOTAL_UNASSIGNED); - - return $criteria; - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Create User - * - * @param array $arrayData Data - * - * return array Return data of the new User created - */ - public function create(array $arrayData) - { - try { - \G::LoadSystem("rbac"); - - //Verify data - $process = new \ProcessMaker\BusinessModel\Process(); - $validator = new \ProcessMaker\BusinessModel\Validator(); - - $validator->throwExceptionIfDataIsNotArray($arrayData, "\$arrayData"); - $validator->throwExceptionIfDataIsEmpty($arrayData, "\$arrayData"); - - //Set data - $arrayData = array_change_key_case($arrayData, CASE_UPPER); - - unset($arrayData["USR_UID"]); - - $this->throwExceptionIfDataIsInvalid("", $arrayData); - - //Create - $cnn = \Propel::getConnection("workflow"); - - try { - $rbac = new \RBAC(); - $user = new \Users(); - - $rbac->initRBAC(); - - $arrayData["USR_PASSWORD"] = \Bootstrap::hashPassword($arrayData["USR_NEW_PASS"]); - - $arrayData["USR_BIRTHDAY"] = (isset($arrayData["USR_BIRTHDAY"]))? $arrayData["USR_BIRTHDAY"] : date("Y-m-d"); - $arrayData["USR_LOGGED_NEXT_TIME"] = (isset($arrayData["USR_LOGGED_NEXT_TIME"]))? $arrayData["USR_LOGGED_NEXT_TIME"] : 0; - $arrayData["USR_CREATE_DATE"] = date("Y-m-d H:i:s"); - $arrayData["USR_UPDATE_DATE"] = date("Y-m-d H:i:s"); - - //Create in rbac - //$userStatus = $arrayData["USR_STATUS"]; - // - //if ($arrayData["USR_STATUS"] == "ACTIVE") { - // $arrayData["USR_STATUS"] = 1; - //} - // - //if ($arrayData["USR_STATUS"] == "INACTIVE") { - // $arrayData["USR_STATUS"] = 0; - //} - // - //$userUid = $this->createUser($arrayData); - // - //if ($arrayData["USR_ROLE"] != "") { - // $this->assignRoleToUser($userUid, $arrayData["USR_ROLE"]); - //} - // - //$arrayData["USR_STATUS"] = $userStatus; - - $userUid = $rbac->createUser($arrayData, $arrayData["USR_ROLE"]); - - //Create in workflow - $arrayData["USR_UID"] = $userUid; - $arrayData["USR_PASSWORD"] = "00000000000000000000000000000000"; - - $result = $user->create($arrayData); - - //User Properties - $userProperty = new \UsersProperties(); - - $aUserProperty = $userProperty->loadOrCreateIfNotExists($arrayData["USR_UID"], array("USR_PASSWORD_HISTORY" => serialize(array(\Bootstrap::hashPassword($arrayData["USR_PASSWORD"]))))); - $aUserProperty["USR_LOGGED_NEXT_TIME"] = $arrayData["USR_LOGGED_NEXT_TIME"]; - - $userProperty->update($aUserProperty); - - //Save Calendar assigment - if (isset($arrayData["USR_CALENDAR"])) { - //Save Calendar ID for this user - \G::LoadClass("calendar"); - - $calendar = new \Calendar(); - $calendar->assignCalendarTo($arrayData["USR_UID"], $arrayData["USR_CALENDAR"], "USER"); - } - - //Return - return $this->getUser($userUid); - } catch (\Exception $e) { - $cnn->rollback(); - - throw $e; - } - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Update User - * - * @param string $userUid Unique id of User - * @param array $arrayData Data - * @param string $userUidLogged Unique id of User logged - * - * return array Return data of the User updated - */ - public function update($userUid, array $arrayData, $userUidLogged) - { - try { - \G::LoadSystem("rbac"); - - //Verify data - $process = new \ProcessMaker\BusinessModel\Process(); - $validator = new \ProcessMaker\BusinessModel\Validator(); - - $validator->throwExceptionIfDataIsNotArray($arrayData, "\$arrayData"); - $validator->throwExceptionIfDataIsEmpty($arrayData, "\$arrayData"); - - //Set data - $arrayData = array_change_key_case($arrayData, CASE_UPPER); - $arrayDataBackup = $arrayData; - - //Verify data - $this->throwExceptionIfNotExistsUser($userUid, $this->arrayFieldNameForException["usrUid"]); - - $this->throwExceptionIfDataIsInvalid($userUid, $arrayData); - - //Permission Admin - $countPermission = 0; - - $permission = $this->loadUserRolePermission("PROCESSMAKER", $userUidLogged); - - foreach ($permission as $key => $value) { - if ($value["PER_CODE"] == "PM_USERS") { - $countPermission = $countPermission + 1; - } - } - - if ($countPermission != 1) { - throw new \Exception(\G::LoadTranslation("ID_USER_CAN_NOT_UPDATE", array($userUidLogged))); - } - - //Update - $cnn = \Propel::getConnection("workflow"); - - try { - $rbac = new \RBAC(); - $user = new \Users(); - - $rbac->initRBAC(); - - if (isset($arrayData["USR_NEW_PASS"])) { - $arrayData["USR_PASSWORD"] = \Bootstrap::hashPassword($arrayData["USR_NEW_PASS"]); - } - - $arrayData["USR_UID"] = $userUid; - $arrayData["USR_LOGGED_NEXT_TIME"] = (isset($arrayData["USR_LOGGED_NEXT_TIME"]))? $arrayData["USR_LOGGED_NEXT_TIME"] : 0; - $arrayData["USR_UPDATE_DATE"] = date("Y-m-d H:i:s"); - - $flagUserLoggedNextTime = false; - - if (isset($arrayData["USR_PASSWORD"])) { - if ($arrayData["USR_PASSWORD"] != "") { - //require_once 'classes/model/UsersProperties.php'; - - $userProperty = new \UsersProperties(); - $aUserProperty = $userProperty->loadOrCreateIfNotExists($userUid, array("USR_PASSWORD_HISTORY" => serialize(array(\Bootstrap::hashPassword($arrayData["USR_PASSWORD"]))))); - - //$memKey = "rbacSession" . session_id(); - //$memcache = & \PMmemcached::getSingleton(defined("SYS_SYS")? SYS_SYS : ""); - // - //if (($rbac->aUserInfo = $memcache->get($memKey)) == false) { - // $rbac->loadUserRolePermission("PROCESSMAKER", $userUidLogged); - // $memcache->set($memKey, $rbac->aUserInfo, \PMmemcached::EIGHT_HOURS); - //} - - if ($rbac->aUserInfo["PROCESSMAKER"]["ROLE"]["ROL_CODE"] == "PROCESSMAKER_ADMIN") { - $aUserProperty["USR_LAST_UPDATE_DATE"] = date("Y-m-d H:i:s"); - $aUserProperty["USR_LOGGED_NEXT_TIME"] = $arrayData["USR_LOGGED_NEXT_TIME"]; - $userProperty->update($aUserProperty); - } - - $aHistory = unserialize($aUserProperty["USR_PASSWORD_HISTORY"]); - - if (!is_array($aHistory)) { - $aHistory = array(); - } - - if (!defined("PPP_PASSWORD_HISTORY")) { - define("PPP_PASSWORD_HISTORY", 0); - } - - if (PPP_PASSWORD_HISTORY > 0) { - //it's looking a password igual into aHistory array that was send for post in md5 way - $c = 0; - $sw = 1; - - while (count($aHistory) >= 1 && count($aHistory) > $c && $sw) { - if (strcmp(trim($aHistory[$c]), trim($arrayData['USR_PASSWORD'])) == 0) { - $sw = 0; - } - - $c++; - } - - if ($sw == 0) { - $sDescription = G::LoadTranslation("ID_POLICY_ALERT") . ":\n\n"; - $sDescription = $sDescription . " - " . G::LoadTranslation("PASSWORD_HISTORY") . ": " . PPP_PASSWORD_HISTORY . "\n"; - $sDescription = $sDescription . "\n" . G::LoadTranslation("ID_PLEASE_CHANGE_PASSWORD_POLICY") . ""; - - throw new \Exception($this->arrayFieldNameForException["usrNewPass"] . ", " . $this->arrayFieldNameForException["usrCnfPass"] . ": " . $sDescription); - } - - if (count($aHistory) >= PPP_PASSWORD_HISTORY) { - $sLastPassw = array_shift($aHistory); - } - - $aHistory[] = $arrayData["USR_PASSWORD"]; - } - - $aUserProperty["USR_LAST_UPDATE_DATE"] = date("Y-m-d H:i:s"); - $aUserProperty["USR_LOGGED_NEXT_TIME"] = $arrayData["USR_LOGGED_NEXT_TIME"]; - $aUserProperty["USR_PASSWORD_HISTORY"] = serialize($aHistory); - $userProperty->update($aUserProperty); - } else { - $flagUserLoggedNextTime = true; - } - } else { - $flagUserLoggedNextTime = true; - } - - if ($flagUserLoggedNextTime) { - //require_once "classes/model/Users.php"; - $oUser = new \Users(); - $aUser = $oUser->load($userUid); - //require_once "classes/model/UsersProperties.php"; - $oUserProperty = new \UsersProperties(); - $aUserProperty = $oUserProperty->loadOrCreateIfNotExists($userUid, array("USR_PASSWORD_HISTORY" => serialize(array($aUser["USR_PASSWORD"])))); - $aUserProperty["USR_LOGGED_NEXT_TIME"] = $arrayData["USR_LOGGED_NEXT_TIME"]; - $oUserProperty->update($aUserProperty); - } - - //Update in rbac - if (isset($arrayData["USR_ROLE"])) { - $rbac->updateUser($arrayData, $arrayData["USR_ROLE"]); - } else { - $rbac->updateUser($arrayData); - } - - //Update in workflow - $result = $user->update($arrayData); - - //Save Calendar assigment - if (isset($arrayData["USR_CALENDAR"])) { - //Save Calendar ID for this user - \G::LoadClass("calendar"); - - $calendar = new \Calendar(); - $calendar->assignCalendarTo($userUid, $arrayData["USR_CALENDAR"], "USER"); - } - - //Return - $arrayData = $arrayDataBackup; - - if (!$this->formatFieldNameInUppercase) { - $arrayData = array_change_key_case($arrayData, CASE_LOWER); - } - - return $arrayData; - } catch (\Exception $e) { - $cnn->rollback(); - - throw $e; - } - } catch (\Exception $e) { - throw $e; - } - } - - /** - * Get data of a User - * - * @param string $userUid Unique id of User - * @param bool $flagGetRecord Value that set the getting - * - * return array Return an array with data of a User - */ - public function getUser($userUid, $flagGetRecord = false) - { - try { - //Verify data - $this->throwExceptionIfNotExistsUser($userUid, $this->arrayFieldNameForException["usrUid"]); - - //Get data - //SQL - $criteria = $this->getUserCriteria(); - - $criteria->add(\UsersPeer::USR_UID, $userUid, \Criteria::EQUAL); - - $rsCriteria = \UsersPeer::doSelectRS($criteria); - $rsCriteria->setFetchmode(\ResultSet::FETCHMODE_ASSOC); - - $rsCriteria->next(); - - $row = $rsCriteria->getRow(); - - //Return - return (!$flagGetRecord)? $this->getUserDataFromRecord($row) : $row; - } catch (\Exception $e) { - throw $e; - } - } - //--- /--- - /** * Create User Uid * @@ -809,7 +71,7 @@ class User $oUserProperty = new \UsersProperties(); $aFields = array(); $dateNow = date('Y-m-d H:i:s'); - $aErrors = $oUserProperty->validatePassword($sPassword, $dateNow, 0); + $aErrors = $oUserProperty->validatePassword($sPassword, $dateNow, $dateNow); if (!empty($aErrors)) { if (!defined('NO_DISPLAY_USERNAME')) { define('NO_DISPLAY_USERNAME', 1); @@ -936,6 +198,478 @@ class User return $fieldsPermissions; } + /** + * Create User + * + * @param array $arrayUserData Data + * + * return array Return data of the new User created + */ + public function create($arrayUserData) + { + try { + require_once (PATH_TRUNK . "workflow" . PATH_SEP . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Users.php"); + $arrayUserData = array_change_key_case($arrayUserData, CASE_UPPER); + $form = $arrayUserData; + if (array_key_exists('USR_REPLACED_BY', $form)) { + if ($form['USR_REPLACED_BY'] != '') { + $oReplacedBy = \UsersPeer::retrieveByPK($form['USR_REPLACED_BY']); + if (is_null($oReplacedBy)) { + throw new \Exception('usr_replaced_by:'.$form['USR_REPLACED_BY'].' '.\G::LoadTranslation('ID_AUTHENTICATION_SOURCE_INVALID')); + } + } + } + if (array_key_exists('USR_COUNTRY', $form)) { + if ($form['USR_COUNTRY'] != '') { + $oCountry = \IsoCountryPeer::retrieveByPK($form['USR_COUNTRY']); + if (is_null($oCountry)) { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array('usr_country'))); + } + } + } + if (array_key_exists('USR_CITY', $form)) { + if ($form['USR_CITY'] != '') { + $oCity = \IsoSubdivisionPeer::retrieveByPK($form['USR_COUNTRY'], $form['USR_CITY']); + if (is_null($oCity)) { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array('usr_city'))); + } + } + } + if (array_key_exists('USR_LOCATION', $form)) { + if ($form['USR_LOCATION'] != '') { + $oLocation = \IsoLocationPeer::retrieveByPK($form['USR_COUNTRY'], $form['USR_LOCATION']); + if (is_null($oLocation)) { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array('usr_location'))); + } + } + } + if (isset($arrayUserData['USR_UID'])) { + $form['USR_UID'] = $arrayUserData['USR_UID']; + } else { + $form['USR_UID'] = ''; + } + if (array_key_exists('USR_NEW_PASS', $form)) { + $sConfirm = $this->testPassword($form['USR_NEW_PASS']); + if ($sConfirm['STATUS'] != 1) { + throw new \Exception('usr_new_pass. '.$sConfirm['DESCRIPTION']); + } + } + if (array_key_exists('USR_NEW_PASS', $form)) { + if ($form['USR_NEW_PASS'] != $form['USR_CNF_PASS']) { + throw new \Exception('usr_new_pass or usr_cnf_pass. '.\G::LoadTranslation('ID_NEW_PASS_SAME_OLD_PASS')); + } + } + if (array_key_exists('USR_NEW_PASS', $form)) { + $form['USR_PASSWORD'] = md5($form['USR_NEW_PASS']); + } + if (!isset($form['USR_CITY'])) { + $form['USR_CITY'] = ''; + } + if (!isset($form['USR_LOCATION'])) { + $form['USR_LOCATION'] = ''; + } + if (!isset($form['USR_AUTH_USER_DN'])) { + $form['USR_AUTH_USER_DN'] = ''; + } + $criteria = new \Criteria(); + $criteria->addSelectColumn(\UsersPeer::USR_USERNAME); + if (array_key_exists('USR_USERNAME', $form)) { + $criteria->add(\UsersPeer::USR_USERNAME, utf8_encode($arrayUserData['USR_USERNAME'])); + } else { + throw new \Exception('usr_name. '.\G::LoadTranslation('ID_MSG_ERROR_USR_USERNAME')); + } + if (\UsersPeer::doCount($criteria) > 0) { + throw new \Exception('usr_username. '.\G::LoadTranslation('ID_USERNAME_ALREADY_EXISTS', array('USER_ID' => $arrayUserData['USR_USERNAME']))); + } + if ($form['USR_USERNAME'] == '') { + throw new \Exception('usr_name. '.\G::LoadTranslation('ID_MSG_ERROR_USR_USERNAME')); + } else { + $userData['USR_USERNAME'] = $form['USR_USERNAME']; + } + $userData['USR_PASSWORD'] = $form['USR_PASSWORD']; + if ($form['USR_FIRSTNAME'] == '') { + throw new \Exception('usr_firstname. '.\G::LoadTranslation('ID_MSG_ERROR_USR_FIRSTNAME')); + } else { + $userData['USR_FIRSTNAME'] = $form['USR_FIRSTNAME']; + } + if ($form['USR_LASTNAME'] == '') { + throw new \Exception('usr_lastname. '.\G::LoadTranslation('ID_MSG_ERROR_USR_LASTNAME')); + } else { + $userData['USR_LASTNAME'] = $form['USR_LASTNAME']; + } + if ($form['USR_EMAIL'] == '') { + throw new \Exception(\G::LoadTranslation("ID_CAN_NOT_BE_NULL", array('usr_email'))); + } else { + if (!filter_var($form['USR_EMAIL'], FILTER_VALIDATE_EMAIL)) { + throw new \Exception('usr_email. '.\G::LoadTranslation('ID_INCORRECT_EMAIL')); + } else { + $userData['USR_EMAIL'] = $form['USR_EMAIL']; + } + } + if ($form['USR_DUE_DATE'] == '') { + throw new \Exception('usr_due_date. '.\G::LoadTranslation('ID_MSG_ERROR_DUE_DATE')); + } else { + $dueDate = explode("-", $form['USR_DUE_DATE']); + if (ctype_digit($dueDate[0])) { + if (checkdate($dueDate[1], $dueDate[2], $dueDate[0]) == false) { + throw new \Exception('usr_due_date. '.\G::LoadTranslation('ID_MSG_ERROR_DUE_DATE')); + } else { + $userData['USR_DUE_DATE'] = $form['USR_DUE_DATE']; + } + } else { + throw new \Exception('usr_due_date. '.\G::LoadTranslation('ID_MSG_ERROR_DUE_DATE')); + } + } + $userData['USR_CREATE_DATE'] = date('Y-m-d H:i:s'); + $userData['USR_UPDATE_DATE'] = date('Y-m-d H:i:s'); + $userData['USR_BIRTHDAY'] = date('Y-m-d'); + $userData['USR_AUTH_USER_DN'] = $form['USR_AUTH_USER_DN']; + $statusWF = $form['USR_STATUS']; + if ($form['USR_STATUS'] == '') { + throw new \Exception(\G::LoadTranslation("ID_CAN_NOT_BE_NULL", array('usr_status'))); + } else { + if ($form['USR_STATUS'] == 'ACTIVE' || $form['USR_STATUS'] == 'INACTIVE' || $form['USR_STATUS'] == 'VACATION') { + $userData['USR_STATUS'] = $form['USR_STATUS']; + } else { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array('usr_status'))); + } + } + if ($form['USR_ROLE'] == '') { + throw new \Exception(\G::LoadTranslation("ID_CAN_NOT_BE_NULL", array('usr_role'))); + } else { + require_once (PATH_RBAC_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Roles.php"); + $oCriteria = new \Criteria('rbac'); + $oCriteria->add(\RolesPeer::ROL_CODE, $form['USR_ROLE']); + $oDataset = \RolesPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + if ($oDataset->getRow()) { + $userData['USR_ROLE'] = $form['USR_ROLE']; + } else { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array('usr_role'))); + } + } + try { + if ($userData['USR_STATUS'] == 'ACTIVE') { + $userData['USR_STATUS'] = 1; + } + if ($userData['USR_STATUS'] == 'INACTIVE') { + $userData['USR_STATUS'] = 0; + } + $sUserUID = $this->createUser($userData); + if ($form['USR_ROLE'] != '') { + $this->assignRoleToUser($sUserUID, $form['USR_ROLE']); + } + } catch(Exception $oError) { + throw new \Exception($oError->getMessage()); + } + $userData['USR_STATUS'] = $statusWF; + $userData['USR_UID'] = $sUserUID; + $userData['USR_COUNTRY'] = $form['USR_COUNTRY']; + $userData['USR_CITY'] = $form['USR_CITY']; + $userData['USR_LOCATION'] = $form['USR_LOCATION']; + $userData['USR_ADDRESS'] = $form['USR_ADDRESS']; + $userData['USR_PHONE'] = $form['USR_PHONE']; + $userData['USR_ZIP_CODE'] = $form['USR_ZIP_CODE']; + $userData['USR_POSITION'] = $form['USR_POSITION']; + $userData['USR_REPLACED_BY'] = $form['USR_REPLACED_BY']; + /*----------------------------------********---------------------------------*/ + $userData['USR_COST_BY_HOUR'] = $form['USR_COST_BY_HOUR']; + $userData['USR_UNIT_COST'] = $form['USR_UNIT_COST']; + /*----------------------------------********---------------------------------*/ + $oUser = new \Users(); + $oUser -> create( $userData ); + if ((isset($form['USR_CALENDAR']))) { + //Save Calendar ID for this user + \G::LoadClass("calendar"); + $calendarObj = new \Calendar(); + $calendarObj->assignCalendarTo($sUserUID, $form['USR_CALENDAR'], 'USER'); + } + $oCriteria = $this->getUser($sUserUID); + return $oCriteria; + } catch (\Exception $e) { + throw $e; + } + } + + /** + * Update User + * + * @param string $usrUid Unique id of User + * @param array $arrayUserData Data + * @param string $usrLoggedUid Unique id of User logged + * + * return array Return data of the User updated + */ + public function update($usrUid, $arrayUserData, $usrLoggedUid) + { + try { + global $RBAC; + $arrayUserData = array_change_key_case($arrayUserData, CASE_UPPER); + $form = $arrayUserData; + $countPermission = 0; + $permission = $this->loadUserRolePermission('PROCESSMAKER', $usrLoggedUid); + foreach ($permission as $key => $value) { + if ($value["PER_CODE"] == 'PM_USERS') { + $countPermission+=1; + } + } + if ($countPermission != 1) { + throw new \Exception(\G::LoadTranslation("ID_USER_CAN_NOT_UPDATE", array($usrLoggedUid))); + } + if (isset($arrayUserData['USR_USERNAME'])) { + $criteria = new \Criteria(); + $criteria->addSelectColumn(\UsersPeer::USR_USERNAME); + $criteria->add(\UsersPeer::USR_USERNAME, utf8_encode($arrayUserData['USR_USERNAME'])); + if (\UsersPeer::doCount($criteria) > 0) { + throw new \Exception('usr_username. '.\G::LoadTranslation('ID_USERNAME_ALREADY_EXISTS', array('USER_ID' => $arrayUserData['USR_USERNAME']))); + } + if ($form['USR_USERNAME'] != '') { + $userData['USR_USERNAME'] = $form['USR_USERNAME']; + } + } + if (isset($usrUid)) { + $form['USR_UID'] = $usrUid; + } else { + $form['USR_UID'] = ''; + } + if (!isset($form['USR_NEW_PASS'])) { + $form['USR_NEW_PASS'] = ''; + } + if ($form['USR_NEW_PASS'] != '') { + $form['USR_PASSWORD'] = md5($form['USR_NEW_PASS']); + } + if (!isset($form['USR_AUTH_USER_DN'])) { + $form['USR_AUTH_USER_DN'] = ''; + } + $userData['USR_UID'] = $form['USR_UID']; + + if (isset($form['USR_PASSWORD'])) { + if ($form['USR_PASSWORD'] != '') { + if ($form['USR_NEW_PASS'] != $form['USR_CNF_PASS']) { + throw new \Exception('usr_new_pass or usr_cnf_pass. '.\G::LoadTranslation('ID_NEW_PASS_SAME_OLD_PASS')); + } + $userData['USR_PASSWORD'] = $form['USR_PASSWORD']; + require_once (PATH_TRUNK . "workflow" . PATH_SEP . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "UsersProperties.php"); + $oUserProperty = new \UsersProperties(); + $aUserProperty = $oUserProperty->loadOrCreateIfNotExists($form['USR_UID'], array('USR_PASSWORD_HISTORY' => serialize(array(md5($form['USR_PASSWORD']))))); + $memKey = 'rbacSession' . session_id(); + $memcache = & \PMmemcached::getSingleton(defined('SYS_SYS') ? SYS_SYS : '' ); + if (($RBAC->aUserInfo = $memcache->get($memKey)) === false) { + $this->loadUserRolePermission('PROCESSMAKER', $usrLoggedUid); + $memcache->set($memKey, $RBAC->aUserInfo, \PMmemcached::EIGHT_HOURS); + } + if ($RBAC->aUserInfo['PROCESSMAKER']['ROLE']['ROL_CODE'] == 'PROCESSMAKER_ADMIN') { + $aUserProperty['USR_LAST_UPDATE_DATE'] = date('Y-m-d H:i:s'); + $aUserProperty['USR_LOGGED_NEXT_TIME'] = 1; + $oUserProperty->update($aUserProperty); + } + $aErrors = $oUserProperty->validatePassword($form['USR_NEW_PASS'], $aUserProperty['USR_LAST_UPDATE_DATE'], 0); + if (count($aErrors) > 0) { + $sDescription = \G::LoadTranslation('ID_POLICY_ALERT') . ':,'; + foreach ($aErrors as $sError) { + switch ($sError) { + case 'ID_PPP_MINIMUN_LENGTH': + $sDescription .= ' - ' . \G::LoadTranslation($sError) . ': ' . PPP_MINIMUN_LENGTH . '. '; + break; + case 'ID_PPP_MAXIMUN_LENGTH': + $sDescription .= ' - ' . \G::LoadTranslation($sError) . ': ' . PPP_MAXIMUN_LENGTH . '. '; + break; + case 'ID_PPP_EXPIRATION_IN': + $sDescription .= ' - ' . \G::LoadTranslation($sError) . ' ' . PPP_EXPIRATION_IN . ' ' . G::LoadTranslation('ID_DAYS') . '. '; + break; + default: + $sDescription .= ' - ' . \G::LoadTranslation($sError) . ','; + break; + } + } + $sDescription .= '' . \G::LoadTranslation('ID_PLEASE_CHANGE_PASSWORD_POLICY'); + throw new \Exception('usr_new_pass or usr_cnf_pass. '.$sDescription); + } + $aHistory = unserialize($aUserProperty['USR_PASSWORD_HISTORY']); + if (!is_array($aHistory)) { + $aHistory = array(); + } + if (!defined('PPP_PASSWORD_HISTORY')) { + define('PPP_PASSWORD_HISTORY', 0); + } + if (PPP_PASSWORD_HISTORY > 0) { + //it's looking a password igual into aHistory array that was send for post in md5 way + $c = 0; + $sw = 1; + while (count($aHistory) >= 1 && count($aHistory) > $c && $sw) { + if (strcmp(trim($aHistory[$c]), trim($form['USR_PASSWORD'])) == 0) { + $sw = 0; + } + $c++; + } + if ($sw == 0) { + $sDescription = \G::LoadTranslation('ID_POLICY_ALERT') . ':

'; + $sDescription .= ' - ' . \G::LoadTranslation('PASSWORD_HISTORY') . ': ' . PPP_PASSWORD_HISTORY . '
'; + $sDescription .= '
' . \G::LoadTranslation('ID_PLEASE_CHANGE_PASSWORD_POLICY') . ''; + throw new \Exception('usr_new_pass or usr_cnf_pass. '.$sDescription); + } + if (count($aHistory) >= PPP_PASSWORD_HISTORY) { + $sLastPassw = array_shift($aHistory); + } + $aHistory[] = $form['USR_PASSWORD']; + } + $aUserProperty['USR_LAST_UPDATE_DATE'] = date('Y-m-d H:i:s'); + $aUserProperty['USR_LOGGED_NEXT_TIME'] = 1; + $aUserProperty['USR_PASSWORD_HISTORY'] = serialize($aHistory); + $oUserProperty->update($aUserProperty); + } + } + if (isset($form['USR_FIRSTNAME'])) { + if ($form['USR_FIRSTNAME'] != '') { + $userData['USR_FIRSTNAME'] = $form['USR_FIRSTNAME']; + } + } + if (isset($form['USR_LASTNAME'])) { + if ($form['USR_LASTNAME'] != '') { + $userData['USR_LASTNAME'] = $form['USR_LASTNAME']; + } + } + if (isset($form['USR_EMAIL'])) { + if ($form['USR_EMAIL'] != '') { + if (!filter_var($form['USR_EMAIL'], FILTER_VALIDATE_EMAIL)) { + throw new \Exception('usr_email. '.\G::LoadTranslation('ID_INCORRECT_EMAIL')); + } else { + $userData['USR_EMAIL'] = $form['USR_EMAIL']; + } + } + } + if (isset($form['USR_DUE_DATE'])) { + if ($form['USR_DUE_DATE'] != '') { + $dueDate = explode("-", $form['USR_DUE_DATE']); + if (ctype_digit($dueDate[0])) { + if (checkdate($dueDate[1], $dueDate[2], $dueDate[0]) == false) { + throw new \Exception('usr_due_date. '.\G::LoadTranslation('ID_MSG_ERROR_DUE_DATE')); + } else { + $userData['USR_DUE_DATE'] = $form['USR_DUE_DATE']; + } + } else { + throw new \Exception('usr_due_date. '.\G::LoadTranslation('ID_MSG_ERROR_DUE_DATE')); + } + } + } + $userData['USR_UPDATE_DATE'] = date('Y-m-d H:i:s'); + if (isset($form['USR_STATUS'])) { + if ($form['USR_STATUS'] != '') { + $userData['USR_STATUS'] = $form['USR_STATUS']; + } + } + if (isset($form['USR_ROLE'])) { + if ($form['USR_ROLE'] != '') { + require_once (PATH_RBAC_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Roles.php"); + $oCriteria = new \Criteria('rbac'); + $oCriteria->add(\RolesPeer::ROL_CODE, $form['USR_ROLE']); + $oDataset = \RolesPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + if ($oDataset->getRow()) { + $userData['USR_ROLE'] = $form['USR_ROLE']; + } else { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array('usr_role'))); + } + $this->updateUser($userData, $form['USR_ROLE']); + } else { + $this->updateUser($userData); + } + } else { + $user = new \Users(); + $dataUser = $user->load($usrUid); + $this->updateUser($userData, $dataUser['USR_ROLE']); + } + if (isset($form['USR_COUNTRY'])) { + if ($form['USR_COUNTRY'] != '') { + $oReplacedBy = \IsoCountryPeer::retrieveByPK($form['USR_COUNTRY']); + if (is_null($oReplacedBy)) { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($form['USR_COUNTRY']))); + } else { + $userData['USR_COUNTRY'] = $form['USR_COUNTRY']; + $userData['USR_CITY'] = ''; + $userData['USR_LOCATION'] = ''; + } + } + } + if (isset($form['USR_CITY'])) { + if ($form['USR_CITY'] != '') { + $oCity = \IsoSubdivisionPeer::retrieveByPK($form['USR_COUNTRY'], $form['USR_CITY']); + if (is_null($oCity)) { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($form['USR_CITY']))); + } else { + $userData['USR_CITY'] = $form['USR_CITY']; + } + } + } + if (isset($form['USR_LOCATION'])) { + if ($form['USR_LOCATION'] != '') { + $oLocation = \IsoLocationPeer::retrieveByPK($form['USR_COUNTRY'], $form['USR_LOCATION']); + if (is_null($oLocation)) { + throw new \Exception(\G::LoadTranslation("ID_INVALID_VALUE_FOR", array($form['USR_LOCATION']))); + } else { + $userData['USR_LOCATION'] = $form['USR_LOCATION']; + } + } + } + if (isset($form['USR_ADDRESS'])) { + $userData['USR_ADDRESS'] = $form['USR_ADDRESS']; + } + if (isset($form['USR_PHONE'])) { + $userData['USR_PHONE'] = $form['USR_PHONE']; + } + if (isset($form['USR_FAX'])) { + $userData['USR_FAX'] = $form['USR_FAX']; + } + if (isset($form['USR_CELLULAR'])) { + $userData['USR_CELLULAR'] = $form['USR_CELLULAR']; + } + if (isset($form['USR_ZIP_CODE'])) { + $userData['USR_ZIP_CODE'] = $form['USR_ZIP_CODE']; + } + if (isset($form['USR_POSITION'])) { + $userData['USR_POSITION'] = $form['USR_POSITION']; + } + if (isset($form['USR_ROLE'])) { + if ($form['USR_ROLE'] != '') { + $userData['USR_ROLE'] = $form['USR_ROLE']; + } + } + /*----------------------------------********---------------------------------*/ + if (isset($form['USR_COST_BY_HOUR'])) { + if ($form['USR_COST_BY_HOUR'] != '') { + $userData['USR_COST_BY_HOUR'] = $form['USR_COST_BY_HOUR']; + } + }if (isset($form['USR_UNIT_COST'])) { + if ($form['USR_UNIT_COST'] != '') { + $userData['USR_UNIT_COST'] = $form['USR_UNIT_COST']; + } + } + /*----------------------------------********---------------------------------*/ + if (isset($form['USR_REPLACED_BY'])) { + if ($form['USR_REPLACED_BY'] != '') { + $oReplacedBy = \UsersPeer::retrieveByPK($form['USR_REPLACED_BY']); + if (is_null($oReplacedBy)) { + throw new \Exception('usr_replaced_by:'.$form['USR_REPLACED_BY'].' '.\G::LoadTranslation('ID_AUTHENTICATION_SOURCE_INVALID')); + } else { + $userData['USR_REPLACED_BY'] = $form['USR_REPLACED_BY']; + } + } + } + if (isset($form['USR_AUTH_USER_DN'])) { + $userData['USR_AUTH_USER_DN'] = $form['USR_AUTH_USER_DN']; + } + require_once (PATH_TRUNK . "workflow" . PATH_SEP . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Users.php"); + $oUser = new \Users(); + $oUser->update($userData); + $oCriteria = $this->getUser($usrUid); + return $oCriteria; + } catch (\Exception $e) { + throw $e; + } + } + /** * Authenticate User * @@ -962,9 +696,6 @@ class User public function delete($usrUid) { try { - //Verify data - $this->throwExceptionIfNotExistsUser($usrUid, $this->arrayFieldNameForException["usrUid"]); - \G::LoadClass('case'); $oProcessMap = new \Cases(); $USR_UID = $usrUid; @@ -1023,9 +754,7 @@ class User try { $aUserInfo = array(); require_once (PATH_TRUNK . "workflow" . PATH_SEP . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Users.php"); - - $oCriteria = $this->getUserCriteria(); - + $oCriteria = new \Criteria(); if ($filter != '') { $oCriteria->add( $oCriteria->getNewCriterion( \UsersPeer::USR_USERNAME, "%$filter%", \Criteria::LIKE )->addOr( $oCriteria->getNewCriterion( \UsersPeer::USR_FIRSTNAME, "%$filter%", \Criteria::LIKE ) )->addOr( $oCriteria->getNewCriterion( \UsersPeer::USR_LASTNAME, "%$filter%", \Criteria::LIKE ) ) ); } @@ -1062,6 +791,40 @@ class User } } + /** + * Get data of a User + * + * @param string $userUid Unique id of User + * + * return array Return an array with data of a User + */ + public function getUser($userUid) + { + try { + $filter = ''; + $aUserInfo = array(); + Validator::usrUid($userUid, '$usr_uid'); + require_once (PATH_TRUNK . "workflow" . PATH_SEP . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Users.php"); + $oCriteria = new \Criteria(); + if ($filter != '') { + $oCriteria->add( $oCriteria->getNewCriterion( \UsersPeer::USR_USERNAME, "%$filter%", \Criteria::LIKE )->addOr( $oCriteria->getNewCriterion( \UsersPeer::USR_FIRSTNAME, "%$filter%", \Criteria::LIKE ) )->addOr( $oCriteria->getNewCriterion( \UsersPeer::USR_LASTNAME, "%$filter%", \Criteria::LIKE ) ) ); + } + $oCriteria->add(\UsersPeer::USR_UID, $userUid); + $oCriteria->add(\UsersPeer::USR_STATUS, 'CLOSED', \Criteria::ALT_NOT_EQUAL); + $oDataset = \UsersPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + while ($oDataset->next()) { + $aRow1 = $oDataset->getRow(); + $aRow1 = array_change_key_case($aRow1, CASE_LOWER); + $aUserInfo = $aRow1; + } + //Return + return $aUserInfo; + } catch (\Exception $e) { + throw $e; + } + } + /** * Upload image User * @@ -1071,17 +834,6 @@ class User public function uploadImage($userUid) { try { - //Verify data - $this->throwExceptionIfNotExistsUser($userUid, $this->arrayFieldNameForException["usrUid"]); - - if (!$_FILES) { - throw new \Exception(\G::LoadTranslation("ID_UPLOAD_ERR_NO_FILE")); - } - - if (!isset($_FILES["USR_PHOTO"])) { - throw new \Exception(\G::LoadTranslation("ID_UNDEFINED_VALUE_IS_REQUIRED", array($this->arrayFieldNameForException["usrPhoto"]))); - } - if ($_FILES['USR_PHOTO']['error'] != 1) { if ($_FILES['USR_PHOTO']['tmp_name'] != '') { $aAux = explode('.', $_FILES['USR_PHOTO']['name']); diff --git a/workflow/engine/src/ProcessMaker/Services/Api/Catalog.php b/workflow/engine/src/ProcessMaker/Services/Api/Catalog.php new file mode 100644 index 000000000..1e9fd1bcd --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Services/Api/Catalog.php @@ -0,0 +1,105 @@ + + * @copyright Colosa - Bolivia + * + * @protected + */ +class Catalog extends Api +{ + /** + * Get Catalog by cat_type + * + * @param string $cat_type {@from path} + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @url GET /:cat_type + * + */ + public function doGetCatalogByType($cat_type) + { + try { + $Catalog = new \ProcessMaker\BusinessModel\Catalog(); + $response = $Catalog->getCatalogByType($cat_type); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @url POST + * + * @param array $request_data + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @status 201 + */ + public function doPost($request_data) + { + try { + $catalog = new \ProcessMaker\BusinessModel\Catalog(); + $arrayData = $catalog->create($request_data); + + $response = $arrayData; + + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @url PUT /:cat_uid/:cat_type + * + * @param string $cat_uid {@min 32}{@max 32} + * @param string $cat_type {@min 32}{@max 32} + * @param array $request_data + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + */ + public function doPut($cat_uid, $cat_type, $request_data) + { + try { + $catalog = new \ProcessMaker\BusinessModel\Catalog(); + + $arrayData = $catalog->update($cat_uid, $cat_type, $request_data); + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @url DELETE /:cat_uid/:cat_type + * + * @param string $cat_uid {@min 32}{@max 32} + * @param string $cat_type {@min 32}{@max 32} + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + */ + public function doDelete($cat_uid, $cat_type) + { + try { + $catalog = new \ProcessMaker\BusinessModel\Catalog(); + + $arrayData = $catalog->delete($cat_uid, $cat_type); + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } +} + diff --git a/workflow/engine/src/ProcessMaker/Services/Api/Dashboard.php b/workflow/engine/src/ProcessMaker/Services/Api/Dashboard.php new file mode 100644 index 000000000..58428f871 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Services/Api/Dashboard.php @@ -0,0 +1,463 @@ + + * @copyright Colosa - Bolivia + * + * @protected + */ +class Dashboard extends Api +{ + /** + * Get dashboards UID by user_uid + * + * @param string $usr_uid {@from path} + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url GET /owner/:usr_uid + * + */ + public function doGetDashboardsUidByUser($usr_uid) + { + try { + $Dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $Dashboard->getDashboardsUidByUser($usr_uid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Get dashboards data by user_uid + * + * @param string $usr_uid {@from path} + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url GET /ownerData/:usr_uid + * + */ + public function doGetDashboardsDataByUser($usr_uid) + { + try { + $Dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $Dashboard->getDashboardDataByUser($usr_uid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Get users by dashboards uid + * + * @param string $das_uid {@from path} + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url GET /users/:das_uid + * + */ + public function doGetDashboardUsers($das_uid) + { + try { + $Dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $Dashboard->getUsersOfDashboard($das_uid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Get dashboards data by uid + * + * @param string $das_uid {@from path} + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url GET /:das_uid + * + */ + public function doGetDashboardData($das_uid) + { + try { + $Dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $Dashboard->getDashboard($das_uid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Get dashboards indicator by dasInd_uid + * + * @param string $dasInd_uid {@from path} + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url GET /indicator/:dasInd_uid + * + */ + public function doGetDashboardIndicator($dasInd_uid) + { + try { + $Dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $Dashboard->getIndicator($dasInd_uid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Get dashboards indicators by dashboardUid + * + * @param string $das_uid {@from path} + * @param string $dateIni {@from path} + * @param string $dateFin {@from path} + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url GET /:das_uid/indicator + * + */ + public function doGetIndicatorsbyDasUid($das_uid, $dateIni="", $dateFin="") + { + try { + $dateIni = ($dateIni=="") ? date("Y/m/d") : $dateIni; + $dateFin = ($dateFin=="") ? date("Y/m/d") : $dateFin; + + $usrUid = $this->getUserId(); + $Dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $Dashboard->getIndicatorsByDasUid($das_uid, $dateIni, $dateFin, $usrUid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Get list Dashboards + * + * @param string $start {@from path} + * @param string $limit {@from path} + * @param string $sort {@from path} + * @param string $dir {@from path} + * @param string $search {@from path} + * @return array + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @url GET + */ + public function doGetListDashboards( + $start = 0, + $limit = 0, + $sort = 'DASHBOARD.DAS_TITLE', + $dir = 'DESC', + $search = '' + ) { + try { + $options['start'] = $start; + $options['limit'] = $limit; + $options['sort'] = $sort; + $options['dir'] = $dir; + $options['search'] = $search; + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->getListDashboards($options); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Get Owners by das_uid + * + * @param string $das_uid {@from path} + * @param string $start {@from path} + * @param string $limit {@from path} + * @param string $search {@from path} + * + * @return array + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @url GET /:das_uid/owners + * + */ + public function doGetOwnersByDasUid( + $das_uid, + $start = 0, + $limit = 0, + $search = '') + { + try { + $options['das_uid'] = $das_uid; + $options['start'] = $start; + $options['limit'] = $limit; + $options['search'] = $search; + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->getOwnerByDasUid($options); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @url POST + * + * @param array $request_data + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @status 201 + */ + public function doPostDashboard($request_data) + { + try { + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->createDashboard($request_data); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Put dashboards configuration + * + * @param array $request_data + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @url PUT + * + */ + public function doPutDashboard($request_data) + { + try { + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->createDashboard($request_data); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @url DELETE /:das_uid + * + * @param string $das_uid {@min 32}{@max 32} + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + */ + public function doDeleteDashboard($das_uid) + { + try { + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->deletedashboard($das_uid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @param array $request_data + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @url POST /owner + * + * @status 201 + */ + public function doPostOwner($request_data) + { + try { + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->createOwner($request_data); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @url DELETE /:das_uid/owner/:owner_uid + * + * @param string $das_uid {@min 32}{@max 32} + * @param string $owner_uid {@min 32}{@max 32} + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + */ + public function doDeleteDashboardOwner($das_uid, $owner_uid) + { + try { + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->deleteDashboardOwner($das_uid, $owner_uid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @param array $request_data + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @url POST /indicator + * + * @status 201 + */ + public function doPostIndicator($request_data) + { + try { + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->createIndicator($request_data); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Put Indicator + * + * @param array $request_data + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + * + * @url PUT /indicator + * + */ + public function doPutIndicator($request_data) + { + try { + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->createIndicator($request_data); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * @url DELETE /indicator/:ind_uid + * + * @param string $ind_uid {@min 32}{@max 32} + * + * @author Marco Antonio Nina + * @copyright Colosa - Bolivia + */ + public function doDeleteIndicator($ind_uid) + { + try { + $dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $dashboard->delete($ind_uid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Post dashboards configuration by userUid + * + * @param array $request_data + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url POST /config/ + * + */ + public function doPostDashboardConfigByUsrUid($request_data) + { + try { + $usrUid = $this->getUserId(); + + $ConfigDashboards = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $ConfigDashboards->postConfigByUsr($request_data, $usrUid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Get dashboards configuration by usr_uid + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url GET /config/ + * + */ + public function doGetDashboardConfigActualUsr() + { + try { + $usrUid = $this->getUserId(); + + $Dashboard = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $Dashboard->getConfig($usrUid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Put dashboards configuration by usr_uid + * + * @param array $request_data + * + * @author Jenny Murillo + * @copyright Colosa - Bolivia + * + * @url PUT /config + * + */ + public function doPutDashboardConfigByUsrUid($request_data) + { + try { + $usrUid = $this->getUserId(); + + $ConfigDashboards = new \ProcessMaker\BusinessModel\Dashboard(); + $response = $ConfigDashboards->putConfigByUsr($request_data, $usrUid); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + +} + diff --git a/workflow/engine/src/ProcessMaker/Services/Api/ReportingIndicators.php b/workflow/engine/src/ProcessMaker/Services/Api/ReportingIndicators.php new file mode 100644 index 000000000..3df2ef4d3 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Services/Api/ReportingIndicators.php @@ -0,0 +1,397 @@ + 1) +// ? $listArray = explode(',', $process_list) +// : null; +// +// $response = $indicatorsObj->getProcessEfficiencyIndex($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date)); +// +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } + + /** + * Lists tasks of a process and it's statistics (efficiency, average times, etc.) + * + * @param string $process_list {@from path} + * @param string $init_date {@from path} + * @param string $end_date {@from path} + * @param string $language {@from path} + * @return array + * + * @url GET /process-tasks + */ + public function doGetProcessTasksInfo($process_list, $init_date, $end_date, $language) + { + + if ($process_list == null || strlen($process_list) <= 1) + throw new InvalidArgumentException ('process_list must have at least a value', 0); + + try { + $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); + $listArray = $listArray = explode(',', $process_list); + $response = $indicatorsObj->getPeiTasksStatistics($listArray, + new \DateTime($init_date), + new \DateTime($end_date), + $language); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + +// /** +// * Returns the aggregate Efficiency of a employee or set of employees +// * +// * @param string $employee_list {@from path} +// * @param string $init_date {@from path} +// * @param string $end_date {@from path} +// * @return array +// * +// * @url GET /employee-efficiency-index +// */ +// public function doGetEmployeeEfficiencyIndex($employee_list, $init_date, $end_date) +// { +// try { +// $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); +// $listArray = (strlen($employee_list) > 1) +// ? $listArray = explode(',', $employee_list) +// : null; +// $response = $indicatorsObj->getEmployeeEfficiencyIndex($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date)); +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } +// +// /** +// * Lists tasks of a employee and it's statistics (efficiency, average times, etc.) +// * +// * @param string $employee_list {@from path} +// * @param string $init_date {@from path} +// * @param string $end_date {@from path} +// * @param string $language {@from path} +// * @return array +// * +// * @url GET /employee-tasks +// */ +// public function doGetEmployeeTasksInfo($employee_list, $init_date, $end_date, $language) +// { +// if ($employee_list == null || strlen($employee_list) <= 1) +// throw new InvalidArgumentException ('employee_list must have at least a value', 0); +// +// try { +// $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); +// $listArray = $listArray = explode(',', $employee_list); +// $response = $indicatorsObj->getEmployeeTasksInfoList($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date), +// $language); +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } +// +// /** +// * Returns the percent of Cases with Overdue time +// * +// * @param string $$process_list {@from path} +// * @param string $init_date {@from path} +// * @param string $end_date {@from path} +// * @return array +// * +// * @url GET /percent-overdue-cases +// */ +// public function doGetPercentOverdueByProcess($process_list, $init_date, $end_date) +// { +// try { +// $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); +// $listArray = (strlen($process_list) > 1) +// ? $listArray = explode(',', $process_list) +// : null; +// $response = $indicatorsObj->getPercentOverdueCasesByProcess($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date)); +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } +// +// /** +// * Returns the percent of Cases with Overdue time with the selected periodicity +// * +// * @param string $$process_list {@from path} +// * @param string $init_date {@from path} +// * @param string $end_date {@from path} +// * @param string $periodicity {@from path} +// * @return array +// * +// * @url GET /percent-overdue-cases-history +// */ +// public function doGetPercentOverdueByProcessHistory($process_list, $init_date, $end_date, $periodicity) +// { +// try { +// $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); +// $listArray = (strlen($process_list) > 1) +// ? $listArray = explode(',', $process_list) +// : null; +// $response = $indicatorsObj->getPercentOverdueCasesByProcessHistory($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date), +// $periodicity); +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } +// +// /** +// * Returns the total of Cases with New time +// * +// * @param string $$process_list {@from path} +// * @param string $init_date {@from path} +// * @param string $end_date {@from path} +// * @return array +// * +// * @url GET /total-new-cases +// */ +// public function doGetTotalNewByProcess($process_list, $init_date, $end_date) +// { +// try { +// $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); +// $listArray = (strlen($process_list) > 1) +// ? $listArray = explode(',', $process_list) +// : null; +// $response = $indicatorsObj->getPercentNewCasesByProcess($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date)); +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } +// +// /** +// * Returns the total of Cases with New time with the selected periodicity +// * +// * @param string $$process_list {@from path} +// * @param string $init_date {@from path} +// * @param string $end_date {@from path} +// * @param string $periodicity {@from path} +// * @return array +// * +// * @url GET /total-new-cases-history +// */ +// public function doGetTotalNewByProcessHistory($process_list, $init_date, $end_date, $periodicity) +// { +// try { +// $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); +// $listArray = (strlen($process_list) > 1) +// ? $listArray = explode(',', $process_list) +// : null; +// $response = $indicatorsObj->getPercentNewCasesByProcessHistory($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date), +// $periodicity); +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } +// +// /** +// * Returns the total of Cases with Completed time +// * +// * @param string $$process_list {@from path} +// * @param string $init_date {@from path} +// * @param string $end_date {@from path} +// * @return array +// * +// * @url GET /total-completed-cases +// */ +// public function doGetTotalCompletedByProcess($process_list, $init_date, $end_date) +// { +// try { +// $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); +// $listArray = (strlen($process_list) > 1) +// ? $listArray = explode(',', $process_list) +// : null; +// $response = $indicatorsObj->getPercentCompletedCasesByProcess($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date)); +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } +// +// /** +// * Returns the total of Cases with Completed time with the selected periodicity +// * +// * @param string $$process_list {@from path} +// * @param string $init_date {@from path} +// * @param string $end_date {@from path} +// * @param string $periodicity {@from path} +// * @return array +// * +// * @url GET /total-completed-cases-history +// */ +// public function doGetTotalCompletedByProcessHistory($process_list, $init_date, $end_date, $periodicity) +// { +// try { +// $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); +// $listArray = (strlen($process_list) > 1) +// ? $listArray = explode(',', $process_list) +// : null; +// $response = $indicatorsObj->getPercentCompletedCasesByProcessHistory($listArray, +// new \DateTime($init_date), +// new \DateTime($end_date), +// $periodicity); +// return $response; +// } catch (\Exception $e) { +// throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); +// } +// } +// + /** + * Returns the total of Cases with Completed time with the selected periodicity + * + * @param string $indicator_uid {@from path} + * @param string $measure_date {@from path} + * @param string $compare_date {@from path} + * @param string $language {@from path} + * @return array + * + * @url GET /process-efficiency-data + */ + public function doGetProcessEficciencyData($indicator_uid, $measure_date, $compare_date, $language) + { + try { + $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); + $response = $indicatorsObj->getPeiCompleteData + ($indicator_uid, + new \DateTime($measure_date), + new \DateTime($compare_date), + $language); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + /** + * Returns the total of Cases with Completed time with the selected periodicity + * + * @param string $indicator_uid {@from path} + * @param string $measure_date {@from path} + * @param string $compare_date {@from path} + * @param string $language {@from path} + * @return array + * + * @url GET /employee-efficiency-data + */ + public function doGetEmployeeEficciencyData($indicator_uid, $measure_date, $compare_date, $language) + { + try { + $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); + $response = $indicatorsObj->getUeiCompleteData + ($indicator_uid, + new \DateTime($measure_date), + new \DateTime($compare_date), + $language); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Returns the total of Cases with Completed time with the selected periodicity + * + * @param string $indicator_uid {@from path} + * @param string $measure_date {@from path} + * @param string $compare_date {@from path} + * @param string $language {@from path} + * @return array + * + * @url GET /group-employee-data + */ + public function doGetGroupEmployeesData($group_uid, $init_date, $end_date, $language) + { + try { + $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); + $response = $indicatorsObj->getUeiGroupsStatistics + ($group_uid, + new \DateTime($init_date), + new \DateTime($end_date), + $language); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + + /** + * Returns the total of Cases with Completed time with the selected periodicity + * + * @param string $indicator_uid {@from path} + * @param string $measure_date {@from path} + * @param string $compare_date {@from path} + * @param string $language {@from path} + * @return array + * + * @url GET /general-indicator-data + */ + public function doGetGeneralIndicatorData ($indicator_uid, $init_date, $end_date, $language) + { + try { + $indicatorsObj = new \ProcessMaker\BusinessModel\ReportingIndicators(); + $response = $indicatorsObj->getGeneralIndicatorStatistics + ($indicator_uid, + new \DateTime($init_date), + new \DateTime($end_date), + $language); + return $response; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } +} + + + + diff --git a/workflow/engine/templates/strategicDashboard/dashboardList.html b/workflow/engine/templates/strategicDashboard/dashboardList.html new file mode 100644 index 000000000..29c2c3e8d --- /dev/null +++ b/workflow/engine/templates/strategicDashboard/dashboardList.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/workflow/engine/templates/strategicDashboard/dashboardList.js b/workflow/engine/templates/strategicDashboard/dashboardList.js new file mode 100644 index 000000000..0489446ce --- /dev/null +++ b/workflow/engine/templates/strategicDashboard/dashboardList.js @@ -0,0 +1,397 @@ +new Ext.KeyMap(document, [ + { + key: Ext.EventObject.F5, + fn: function(k, e) { + if (!e.ctrlKey) { + if (Ext.isIE) { + e.browserEvent.keyCode = 8; + } + e.stopEvent(); + document.location = document.location; + } else { + Ext.Msg.alert(_('ID_REFRESH_LABEL'), _('ID_REFRESH_MESSAGE')); + } + } + }, + { + key: Ext.EventObject.DELETE, + fn: function(k, e) { + iGrid = Ext.getCmp('infoGrid'); + rowSelected = iGrid.getSelectionModel().getSelected(); + if (rowSelected) { + deleteDashboard(); + } + } + }, + { + key: Ext.EventObject.F2, + fn: function(k, e) { + iGrid = Ext.getCmp('infoGrid'); + rowSelected = iGrid.getSelectionModel().getSelected(); + if (rowSelected){ + editDashboard(); + } + } + } +]); + +var store; +var cmodel; +var infoGrid; +var viewport; +var smodel; +var newButton; +var editButton; +var deleteButton; +var statusButton; +var actionButtons; +var contextMenu; +var myMask; + +Ext.onReady(function() { + Ext.QuickTips.init(); + + pageSize = 20; + myMask = new Ext.LoadMask(Ext.getBody(), {msg:_('ID_LOADING')}); + + newButton = new Ext.Action({ + text: _('ID_NEW'), + iconCls: 'button_menu_ext ss_sprite ss_add', + handler: newDashboard + }); + + editButton = new Ext.Action({ + text: _('ID_EDIT'), + iconCls: 'button_menu_ext ss_sprite ss_pencil', + handler: editDashboard, + disabled: true + }); + + deleteButton = new Ext.Action({ + text: _('ID_DELETE'), + iconCls: 'button_menu_ext ss_sprite ss_delete', + handler: deleteDashboard, + disabled: true + }); + + statusButton = new Ext.Action({ + text: _('ID_STATUS'), + iconCls: 'silk-add', + handler: statusDashboard, + disabled: true + }); + + contextMenu = new Ext.menu.Menu({ + items: [editButton, deleteButton, statusButton] + }); + + actionButtons = [newButton, '-', editButton, deleteButton, statusButton]; + + smodel = new Ext.grid.RowSelectionModel({ + singleSelect: true, + listeners:{ + rowselect: function(sm, index, record) { + editButton.disable(); + deleteButton.disable(); + statusButton.enable(); + + if (typeof(_rowselect) !== 'undefined') { + if (Ext.isArray(_rowselect)) { + for (var i = 0; i < _rowselect.length; i++) { + if (Ext.isFunction(_rowselect[i])) { + _rowselect[i](sm, index, record); + } + } + } + } + + if( record.data.DAS_STATUS == 1 ){ + statusButton.setIconClass('icon-activate'); + statusButton.setText( _('ID_DEACTIVATE') ); + editButton.enable(); + deleteButton.enable(); + //statusButton.enable(); + } else { + statusButton.setIconClass('icon-deactivate'); + statusButton.setText( _('ID_ACTIVATE') ); + editButton.disable(); + deleteButton.disable(); + //statusButton.disable(); + } + }, + rowdeselect: function(sm, index, record){ + editButton.disable(); + deleteButton.disable(); + statusButton.disable(); + if (typeof(_rowdeselect) !== 'undefined') { + if (Ext.isArray(_rowdeselect)) { + for (var i = 0; i < _rowdeselect.length; i++) { + if (Ext.isFunction(_rowdeselect[i])) { + _rowdeselect[i](sm, index, record); + } + } + } + } + } + } + }); + + store = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + api: { + read : urlProxy + 'dashboard' + } + ,method: 'GET' + ,headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + } + }), + reader : new Ext.data.JsonReader( { + root: 'data', + totalProperty: 'total', + fields : [ + {name : 'DAS_UID'}, + {name : "DAS_TITLE"}, + {name : 'DAS_DESCRIPTION'}, + {name : 'DAS_OWNER'}, + {name : 'DAS_UPDATE_DATE'}, + {name : 'DAS_LABEL_STATUS'}, + {name : 'DAS_STATUS'} + ] + }), + sortInfo: { + field: 'DAS_TITLE', + direction: 'ASC' + } + }); + + var formatLineWrap = function (value) { + str = '
'+value+'
'; + return str; + }; + + cmodel = new Ext.grid.ColumnModel({ + defaults: { + width: 50, + sortable: true + }, + columns: [ + {id:'DAS_UID', dataIndex: 'DAS_UID', hidden:true, hideable:false}, + {header: _("ID_TITLE"), dataIndex: "DAS_TITLE", width: 150, hidden: false, align: "left", renderer : formatLineWrap}, + {header: _("ID_DESCRIPTION"), dataIndex: "DAS_DESCRIPTION", width: 200, hidden: false, align: "left"}, + {header: _('ID_ASSIGNED_TO'), dataIndex: 'DAS_OWNER', width: 200, hidden: false, align: 'center'}, + {header: _('ID_UPDATE_DATE'), dataIndex: 'DAS_UPDATE_DATE', width: 80, hidden: false, align: 'center'}, + {header: _('ID_STATUS'), dataIndex: 'DAS_LABEL_STATUS', width: 60, hidden: false, align: 'center'} + ] + }); + + storePageSize = new Ext.data.SimpleStore({ + fields: ['size'], + data: [['20'],['30'],['40'],['50'],['100']], + autoLoad: true + }); + + comboPageSize = new Ext.form.ComboBox({ + typeAhead : false, + mode : 'local', + triggerAction : 'all', + store: storePageSize, + valueField: 'size', + displayField: 'size', + width: 50, + editable: false, + listeners:{ + select: function(c,d,i){ + bbarpaging.pageSize = parseInt(d.data['size']); + bbarpaging.moveFirst(); + } + } + }); + + comboPageSize.setValue(pageSize); + + bbarpaging = new Ext.PagingToolbar({ + pageSize: pageSize, + store: store, + displayInfo: true, + displayMsg: _('ID_GRID_PAGE_DISPLAYING_DASHBOARD_MESSAGE') + '    ', + //displayMsg: 'Displaying Dashboards s {0} - {1} of {2}' + '    ', + emptyMsg: _('ID_GRID_PAGE_NO_DASHBOARD_MESSAGE'), + //emptyMsg: 'No Dashboards s to display', + items: ['-',_('ID_PAGE_SIZE')+':',comboPageSize] + }); + + infoGrid = new Ext.grid.GridPanel({ + region: 'center', + layout: 'fit', + id: 'infoGrid', + height:100, + autoWidth : true, + stateful : true, + stateId : 'gridDashboardList', + enableColumnResize: true, + enableHdMenu: true, + frame:false, + columnLines: false, + viewConfig: { + forceFit:true + }, + title : _('ID_DASHBOARD'), + store: store, + cm: cmodel, + sm: smodel, + tbar: actionButtons, + bbar: bbarpaging, + listeners: { + rowdblclick: editDashboard, + render: function(){ + this.loadMask = new Ext.LoadMask(this.body, {msg:_('ID_LOADING_GRID')}); + } + }, + view: new Ext.grid.GroupingView({ + forceFit:true, + groupTextTpl: '{text}', + cls:"x-grid-empty", + emptyText: _('ID_NO_RECORDS_FOUND') + }) + }); + + infoGrid.on('rowcontextmenu', + function (grid, rowIndex, evt) { + var sm = grid.getSelectionModel(); + sm.selectRow(rowIndex, sm.isSelected(rowIndex)); + }, + this + ); + + infoGrid.on('contextmenu', + function (evt) { + evt.preventDefault(); + }, + this + ); + + infoGrid.addListener('rowcontextmenu',onMessageContextMenu,this); + + infoGrid.store.load(); + + viewport = new Ext.Viewport({ + layout: 'fit', + autoScroll: false, + items: [ + infoGrid + ] + }); + + if (typeof(__DASHBOARD_ERROR__) !== 'undefined') { + PMExt.notify(_('ID_DASHBOARD'), __DASHBOARD_ERROR__); + } +}); + +//Funtion Handles Context Menu Opening +onMessageContextMenu = function (grid, rowIndex, e) { + e.stopEvent(); + var coords = e.getXY(); + contextMenu.showAt([coords[0], coords[1]]); +}; + +//Load Grid By Default +gridByDefault = function() { + infoGrid.store.load(); +}; + +//New Dashboard Action +newDashboard = function() { + location.href = 'formDashboard'; +}; + +//Edit Dashboard Action +editDashboard = function() { + var rowSelected = infoGrid.getSelectionModel().getSelected(); + if (rowSelected){ + location.href = 'formEditDashboard?DAS_UID=' + rowSelected.data.DAS_UID; + } +}; + +//Delete Dashboard Action +deleteDashboard = function() { + var rowSelected = infoGrid.getSelectionModel().getSelected(); + if (rowSelected) { + Ext.Msg.confirm(_('ID_CONFIRM'), _('ID_CONFIRM_DELETE_DASHBOARD'),function(btn, text) + { + if (btn == 'yes') { + viewport.getEl().mask(_('ID_PROCESSING')); + Ext.Ajax.request({ + url : urlProxy + 'dashboard/' + rowSelected.data.DAS_UID, + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + }, + success: function (result, request) { + viewport.getEl().unmask(); + response = Ext.util.JSON.decode(result.responseText); + PMExt.notify(_('ID_DASHBOARD'),_('ID_DASHBOARD_SUCCESS_DELETE')); + editButton.disable(); + deleteButton.disable(); + infoGrid.store.load(); + }, + failure: function (result, request) { + Ext.MessageBox.alert( _('ID_ALERT'), _('ID_AJAX_COMMUNICATION_FAILED') ); + } + }); + } + }); + } +}; + +//Status Dashboard Action +statusDashboard = function() { + var rows = infoGrid.getSelectionModel().getSelections(); + if( rows.length > 0 ) { + for (i=0; i +
+
\ No newline at end of file diff --git a/workflow/engine/templates/strategicDashboard/formDashboard.js b/workflow/engine/templates/strategicDashboard/formDashboard.js new file mode 100644 index 000000000..35f625a9a --- /dev/null +++ b/workflow/engine/templates/strategicDashboard/formDashboard.js @@ -0,0 +1,1289 @@ +new Ext.KeyMap(document, [ + { + key: Ext.EventObject.F5, + fn: function(k, e) { + if (!e.ctrlKey) { + if (Ext.isIE) { + e.browserEvent.keyCode = 8; + } + e.stopEvent(); + document.location = document.location; + } else { + Ext.Msg.alert(_('ID_REFRESH_LABEL'), _('ID_REFRESH_MESSAGE')); + } + } + }, + { + key: Ext.EventObject.DELETE, + fn: function(k, e) { + iGrid = Ext.getCmp('ownerInfoGrid'); + rowSelected = iGrid.getSelectionModel().getSelected(); + if (rowSelected) { + deleteDashboard(); + } + } + }, + { + key: Ext.EventObject.F2, + fn: function(k, e) { + iGrid = Ext.getCmp('ownerInfoGrid'); + rowSelected = iGrid.getSelectionModel().getSelected(); + if (rowSelected){ + editDashboard(); + } + } + } +]); + +var viewport; +var dashboardFields; +var frmDashboard; +var addTabButton; +var tabPanel; +var dashboardIndicatorFields; +var dashboardIndicatorPanel; +var store; + +var indexTab = 0; +var comboPageSize = 10; +var resultTpl; +var storeIndicatorType; +var storeGraphic; +var storeFrecuency; +var storeProject; +var storeGroup; +var storeUsers; +var dataUserGroup; +var dasIndUid; +var flag = true; +var myMask; +var dataIndicator = ''; +var tabActivate = []; + +Ext.onReady( function() { + + myMask = new Ext.LoadMask(Ext.getBody(), {msg:_('ID_LOADING')}); + + + Ext.QuickTips.init(); + + resultTpl = new Ext.XTemplate( + '
', + ' {APP_PRO_TITLE}', + '
' + ); + + //FieldSets + dashboardFields = new Ext.form.FieldSet({ + title : _('ID_GENERATE_INFO'), + items : [ + { + id : 'DAS_TITLE', + fieldLabel : _('ID_DASHBOARD_TITLE'), + xtype : 'textfield', + anchor : '85%', + maxLength : 250, + maskRe : /([a-zA-Z0-9\s]+)$/, + allowBlank : false + }, + { + xtype : 'textarea', + id : 'DAS_DESCRIPTION', + fieldLabel : _('ID_DESCRIPTION'), + labelSeparator : '', + anchor : '85%', + maskRe : /([a-zA-Z0-9\s]+)$/, + height : 50, + } + ] + }); + + //grid owner + deleteButton = new Ext.Action({ + text : _('ID_DELETE'), + iconCls : 'button_menu_ext ss_sprite ss_delete', + handler : deleteOwner, + disabled: true + }); + + actionButtons = [deleteButton]; + + + var owner = Ext.data.Record.create ([ + { + name : 'DAS_UID', + type: 'string' + }, + { + name : "OWNER_UID", + type: 'string' + }, + { + name : "OWNER_LABEL", + type: 'string' + }, + { + name : 'OWNER_TYPE', + type: 'string' + } + ]); + + store = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + api: { + read : urlProxy + 'dashboard/'+ DAS_UID +'/owners' + } + ,method: 'GET' + ,headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + } + }), + reader : new Ext.data.JsonReader( { + root: 'owner', + totalProperty: 'totalCount', + fields : owner + }), + sortInfo: { + field: 'OWNER_TYPE', + direction: 'ASC' + } + }); + + storeGroup = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + api: { + read : urlProxy + 'group' + } + ,method: 'GET' + ,headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + } + }), + reader : new Ext.data.JsonReader( { + fields : [ + {name : 'grp_uid'}, + {name : "grp_title"}, + {name : "grp_status"}, + {name : "grp_users"}, + {name : 'grp_tasks'} + ] + }), + sortInfo: { + field: 'grp_title', + direction: 'ASC' + } + }); + storeGroup.load(); + + storeUsers = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + api: { + read : urlProxy + 'users' + } + ,method: 'GET' + ,headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + } + }), + reader : new Ext.data.JsonReader( { + fields : [ + {name : 'usr_uid'}, + {name : "usr_firstname"}, + {name : "usr_lastname"}, + {name : 'usr_status'} + ] + }), + sortInfo: { + field: 'usr_lastname', + direction: 'ASC' + } + }); + storeUsers.load(); + + bbarpaging = new Ext.PagingToolbar({ + pageSize: 10, + store: store, + displayInfo: true, + displayMsg: _('ID_GRID_PAGE_DISPLAYING_0WNER_MESSAGE') + '    ', + emptyMsg: _('ID_GRID_PAGE_NO_OWNER_MESSAGE'), + }); + + cmodel = new Ext.grid.ColumnModel({ + defaults: { + width: 50, + sortable: true + }, + columns: [ + { id:'DAS_UID', dataIndex: 'DAS_UID', hidden:true, hideable:false}, + { header: _("ID_OWNER"), dataIndex: "OWNER_LABEL", width: 150, hidden: false, align: "left"}, + { header: _("ID_OWNER_TYPE"), dataIndex: "OWNER_TYPE", width: 80, hidden: false, align: "left"} + ] + }); + + smodel = new Ext.grid.RowSelectionModel({ + singleSelect: true, + listeners:{ + rowselect: function(sm, index, record) { + deleteButton.enable(); + }, + rowdeselect: function(sm, index, record){ + deleteButton.disable(); + } + } + }); + + + storeIndicatorType = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + api: { + read : urlProxy + 'catalog/indicator' + } + ,method: 'GET' + ,headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + } + }), + reader : new Ext.data.JsonReader( { + fields : [ + {name : 'CAT_UID'}, + {name : 'CAT_LABEL_ID'}, + {name : 'CAT_TYPE'}, + {name : 'CAT_FLAG'}, + {name : 'CAT_OBSERVATION'}, + {name : 'CAT_CREATE_DATE'}, + {name : 'CAT_UPDATE_DATE'} + ] + }), + sortInfo: { + field: 'CAT_LABEL_ID', + direction: 'ASC' + } + }); + + storeGraphic = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + api: { + read : urlProxy + 'catalog/graphic' + } + ,method: 'GET' + ,headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + } + }), + reader : new Ext.data.JsonReader( { + fields : [ + {name : 'CAT_UID'}, + {name : 'CAT_LABEL_ID'}, + {name : 'CAT_TYPE'}, + {name : 'CAT_FLAG'}, + {name : 'CAT_OBSERVATION'}, + {name : 'CAT_CREATE_DATE'}, + {name : 'CAT_UPDATE_DATE'} + ] + }), + sortInfo: { + field: 'CAT_LABEL_ID', + direction: 'ASC' + } + }); + + storeFrecuency = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + api: { + read : urlProxy + 'catalog/periodicity' + } + ,method: 'GET' + ,headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + } + }), + reader : new Ext.data.JsonReader( { + fields : [ + {name : 'CAT_UID'}, + {name : 'CAT_LABEL_ID'}, + {name : 'CAT_TYPE'}, + {name : 'CAT_FLAG'}, + {name : 'CAT_OBSERVATION'}, + {name : 'CAT_CREATE_DATE'}, + {name : 'CAT_UPDATE_DATE'} + ] + }), + sortInfo: { + field: 'CAT_LABEL_ID', + direction: 'ASC' + } + }); + + var project = Ext.data.Record.create ([ + { + name : 'prj_uid', + type: 'string' + }, + { + name : 'prj_name', + type: 'string' + }, + { + name : 'prj_description', + type: 'string' + }, + { + name : 'prj_category', + type: 'string' + }, + { + name : 'prj_type', + type: 'string' + }, + { + name : 'prj_create_date', + type: 'string' + }, + { + name : 'prj_update_date', + type: 'string' + } + ]); + + storeProject = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + api: { + read : urlProxy + 'project' + } + ,method: 'GET' + ,headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + credentials.access_token + } + }), + reader : new Ext.data.JsonReader( { + fields :project + }), + sortInfo: { + field: 'prj_name', + direction: 'ASC' + }, + listeners: { + load: function( store ) { + var p = new project({ + prj_name: _('ID_ALL_PROCESS'), + prj_uid: '0', + prj_description: '0', + prj_category: '0', + prj_type: '0', + prj_create_date: '0', + prj_update_date: '0' + }); + store.insert(0, p); + } + } + }); + + ownerInfoGrid = new Ext.grid.GridPanel({ + region : 'center', + layout : 'fit', + id : 'ownerInfoGrid', + height : 200, + autoWidth : true, + //anchor : '80%', + stateful : true, + stateId : 'gridDashboardList', + enableColumnResize : true, + enableHdMenu: true, + frame : false, + columnLines : false, + viewConfig : { + forceFit:true + }, + store: store, + cm: cmodel, + sm: smodel, + tbar: actionButtons, + bbar: bbarpaging, + listeners: { + render: function(){ + this.loadMask = new Ext.LoadMask(this.body, {msg:_('ID_LOADING_GRID')}); + } + }, + view: new Ext.grid.GroupingView({ + forceFit:true, + groupTextTpl: '{text}', + cls:"x-grid-empty", + emptyText: _('ID_NO_RECORDS_FOUND') + }) + }); + + dashboardOwnerFields = new Ext.form.FieldSet({ + title : _('ID_OWNER_INFORMATION'), + collapsible : true, + //collapsed : true, + items : [ + { + xtype : 'combo', + id : 'searchIem', + anchor : '60%', + typeAhead : false, + hideLabel : true, + hideTrigger : true, + editable : true, + fieldLabel : _('ID_SELECT'), + displayField : 'field1', + emptyText : _('ID_ENTER_SEARCH_TERM'), + mode : 'local', + autocomplete : true, + triggerAction : 'all', + maskRe : /([a-zA-Z0-9\s]+)$/, + store : new Ext.data.ArrayStore({ + fields : ['owner_uid','owner_label','owner_type'], + data : dataUserGroup + }), + listConfig : { + loadingText: _('ID_SEARCH'), + emptyText: _('ID_NO_FIELD_FOUND'), + getInnerTpl: function() { + return '
' + + '

{owner_uid}{owner_label}

' + + '{excerpt}' + + '
'; + } + }, + //pageSize : 10, + listeners :{ + scope : this, + select : function(combo, selection) { + var sw = false; + var data = store.data.items; + for (var i=0; i 3 ) { + PMExt.warning(_('ID_DASHBOARD'), _('ID_MAX_INDICATOR_DASHBOARD')); + return false; + } + tabPanel.add({ + //title : _('ID_INDICATOR') + (++indexTab), + title : _('ID_INDICATOR')+ ' '+ (++indexTab), + id : indexTab, + iconCls : 'tabs', + items : [ + new Ext.Panel({ + height : 260, + border : true, + bodyStyle : 'padding:10px', + items : [ + new Ext.form.FieldSet({ + labelWidth : 150, + labelAlign :'right', + items : [ + { + id : 'DAS_IND_UID_' + indexTab, + xtype : 'textfield', + hidden : true + }, + { + fieldLabel : _('ID_INDICATOR_TITLE'), + id : 'IND_TITLE_'+ indexTab, + xtype : 'textfield', + anchor : '85%', + maskRe : /([a-zA-Z0-9\s]+)$/, + maxLength : 250, + allowBlank : false + }, + new Ext.form.ComboBox({ + anchor : '85%', + editable : false, + id : 'IND_TYPE_'+ indexTab, + fieldLabel : _('ID_INDICATOR_TYPE'), + displayField : 'CAT_LABEL_ID', + valueField : 'CAT_UID', + forceSelection : false, + emptyText : _('ID_SELECT'), + selectOnFocus : true, + typeAhead : true, + autocomplete : true, + triggerAction : 'all', + store : storeIndicatorType, + listeners:{ + scope: this, + select: function(combo, record, index) { + var value = combo.getValue(); + var index = tabPanel.getActiveTab().id; + var fields = ['DAS_IND_FIRST_FIGURE_'+index,'DAS_IND_FIRST_FREQUENCY_'+index,'DAS_IND_SECOND_FIGURE_'+index, 'DAS_IND_SECOND_FREQUENCY_'+index]; + if (value == '1010' || value == '1030') { + for (var i=0; i